From 8f14b0feb977d065dbd3b9dfc22493cadcc87e57 Mon Sep 17 00:00:00 2001 From: Tueem Date: Wed, 19 Feb 2025 21:49:12 +0100 Subject: [PATCH 01/22] split up getSubCommands --- .../commands/SlashCommandDefinition.java | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java index 9b0b3fb..376f7a2 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java @@ -51,21 +51,16 @@ public class SlashCommandDefinition { subCommandGroupMap.put(x.name(), x); }); - return subCommandGroupMap.values().toArray(new SubCommandGroup[0]); + return subCommandGroupMap.values().toArray(SubCommandGroup[]::new); } - public SubCommand[] getSubCommands(String groupName) { + public SubCommand[] getSubCommands() { List subCommands; - if (groupName == null) - subCommands = Arrays.stream(getExecutableDefinitons()) - .filter((x) -> x.subCommandGroup() == null && x.subCommand() != null) - .map((x) -> x.subCommand()) - .toList(); - else - subCommands = Arrays.stream(getExecutableDefinitons()) - .filter((x) -> x.subCommandGroup().name().equals(groupName) && x.subCommand() != null) - .map((x) -> x.subCommand()) - .toList(); + subCommands = Arrays.stream(getExecutableDefinitons()) + .filter((x) -> x.subCommandGroup() == null && x.subCommand() != null) + .map((x) -> x.subCommand()) + .toList(); + HashMap subCommandMap = new HashMap<>(); subCommands.forEach((x) -> { @@ -74,18 +69,24 @@ public class SlashCommandDefinition { subCommandMap.put(x.name(), x); }); - return subCommandMap.values().toArray(new SubCommand[0]); + return subCommandMap.values().toArray(SubCommand[]::new); } - public SlashCommand getFullSlashCommand() { - if (isRootCommand()) - return getSlashCommand(); - for (ExecutableSlashCommandDefinition executableSlashCommandDefinition : executableDefinitons) { - if (executableSlashCommandDefinition.options().length > 0) - return executableSlashCommandDefinition.applicationCommand(); - } + public SubCommand[] getSubCommands(String groupName) { + List subCommands; + subCommands = Arrays.stream(getExecutableDefinitons()) + .filter((x) -> x.subCommandGroup().name().equals(groupName) && x.subCommand() != null) + .map((x) -> x.subCommand()) + .toList(); + + HashMap subCommandMap = new HashMap<>(); + subCommands.forEach((x) -> { + SubCommand current = subCommandMap.get(x.name()); + if (current == null || (current.description().isBlank() && !x.description().isBlank())) + subCommandMap.put(x.name(), x); + }); - return null; + return subCommandMap.values().toArray(SubCommand[]::new); } public SlashCommand getSlashCommand() { -- 2.47.2 From 9058629af59c6aff1fa499d69367edb145ca9b14 Mon Sep 17 00:00:00 2001 From: Tueem Date: Wed, 19 Feb 2025 21:50:54 +0100 Subject: [PATCH 02/22] remove redundant getFullSlashCommand --- .../marinara/wrapper/discord4j/Discord4JWrapper.java | 7 ++++--- .../marinara/wrapper/javacord/JavacordWrapper.java | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java index 66df289..d276aaf 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -81,8 +81,8 @@ public class Discord4JWrapper extends LibraryWrapper { for (SlashCommandDefinition slashCommandDefinition : defs) { ApplicationCommandRequest request = convertSlashCommand(slashCommandDefinition); - if (slashCommandDefinition.getFullSlashCommand().serverIds().length > 0) { - for (long serverId : slashCommandDefinition.getFullSlashCommand().serverIds()) { + if (slashCommandDefinition.getSlashCommand().serverIds().length > 0) { + for (long serverId : slashCommandDefinition.getSlashCommand().serverIds()) { serverCommands.putIfAbsent(serverId, new ArrayList<>()); serverCommands.get(serverId).add(request); } @@ -132,7 +132,7 @@ public class Discord4JWrapper extends LibraryWrapper { private ApplicationCommandRequest convertSlashCommand(SlashCommandDefinition def) { List options = new ArrayList<>(); - SlashCommand cmd = def.getFullSlashCommand(); + SlashCommand cmd = def.getSlashCommand(); 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); @@ -191,6 +191,7 @@ public class Discord4JWrapper extends LibraryWrapper { builder.value(choice.doubleValue()); if (!choice.stringValue().isEmpty()) builder.value(choice.stringValue()); + convertedChoices.add(builder.build()); } return convertedChoices; } 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 e8555bb..6659ca2 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 @@ -65,8 +65,8 @@ public class JavacordWrapper extends LibraryWrapper { Set globalCommands = new HashSet<>(); for (SlashCommandDefinition slashCommandDefinition : defs) { SlashCommandBuilder builder = convertSlashCommand(slashCommandDefinition); - if (slashCommandDefinition.getFullSlashCommand().serverIds().length > 0) { - for (long serverId : slashCommandDefinition.getFullSlashCommand().serverIds()) { + if (slashCommandDefinition.getSlashCommand().serverIds().length > 0) { + for (long serverId : slashCommandDefinition.getSlashCommand().serverIds()) { serverCommands.putIfAbsent(serverId, new HashSet<>()); serverCommands.get(serverId).add(builder); } @@ -106,7 +106,7 @@ public class JavacordWrapper extends LibraryWrapper { private SlashCommandBuilder convertSlashCommand(SlashCommandDefinition def) { List options = new ArrayList<>(); - SlashCommand cmd = def.getFullSlashCommand(); + SlashCommand cmd = def.getSlashCommand(); 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); @@ -164,6 +164,7 @@ public class JavacordWrapper extends LibraryWrapper { */ if (!choice.stringValue().isEmpty()) builder.setValue(choice.stringValue()); + convertedChoices.add(builder.build()); } return convertedChoices; } -- 2.47.2 From f6db113deba8a90f70812613b2bd72d21e3db1ab Mon Sep 17 00:00:00 2001 From: Tueem Date: Thu, 20 Feb 2025 00:41:15 +0100 Subject: [PATCH 03/22] add CommandConverter stub --- .../commands/CommandConverter.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java new file mode 100644 index 0000000..fcbfb85 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java @@ -0,0 +1,23 @@ +package net.tomatentum.marinara.interaction.commands; + +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; +import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; +import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup; + +public class CommandConverter { + + private Spec spec; + + public A convert(SlashCommandDefinition def) { + return null; + } + + public interface Spec { + + public A convertCommand(SlashCommandDefinition def); + public O convertSubCommand(SubCommand def, O[] options); + public O convertSubCommandGroup(SubCommandGroup def, O[] options); + public O convertOption(SlashCommandOption option, C[] choices); + public C[] convertChoice(SlashCommandOption option); + } +} -- 2.47.2 From 236c584da8be1163a1a8732bb9ec9ae7931a1072 Mon Sep 17 00:00:00 2001 From: tueem Date: Thu, 20 Feb 2025 09:10:28 +0100 Subject: [PATCH 04/22] move Choice classes --- .../interaction/commands/ExecutableSlashCommandDefinition.java | 1 + .../interaction/commands/{ => choice}/ChoiceValueProvider.java | 2 +- .../marinara/interaction/commands/{ => choice}/EnumChoices.java | 2 +- .../net/tomatentum/marinara/test/discord4j/TestChoiceEnum.java | 2 +- .../net/tomatentum/marinara/test/javacord/TestChoiceEnum.java | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) rename lib/src/main/java/net/tomatentum/marinara/interaction/commands/{ => choice}/ChoiceValueProvider.java (53%) rename lib/src/main/java/net/tomatentum/marinara/interaction/commands/{ => choice}/EnumChoices.java (98%) diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java index 76bc8eb..480d363 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java @@ -6,6 +6,7 @@ import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptio import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption.PlaceHolderEnum; +import net.tomatentum.marinara.interaction.commands.choice.EnumChoices; public record ExecutableSlashCommandDefinition( SlashCommand applicationCommand, diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ChoiceValueProvider.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/choice/ChoiceValueProvider.java similarity index 53% rename from lib/src/main/java/net/tomatentum/marinara/interaction/commands/ChoiceValueProvider.java rename to lib/src/main/java/net/tomatentum/marinara/interaction/commands/choice/ChoiceValueProvider.java index b7d13f6..b025047 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ChoiceValueProvider.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/choice/ChoiceValueProvider.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.interaction.commands; +package net.tomatentum.marinara.interaction.commands.choice; public interface ChoiceValueProvider { T getChoiceValue(); diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/EnumChoices.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/choice/EnumChoices.java similarity index 98% rename from lib/src/main/java/net/tomatentum/marinara/interaction/commands/EnumChoices.java rename to lib/src/main/java/net/tomatentum/marinara/interaction/commands/choice/EnumChoices.java index 1001db3..f012c1f 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/EnumChoices.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/choice/EnumChoices.java @@ -1,4 +1,4 @@ -package net.tomatentum.marinara.interaction.commands; +package net.tomatentum.marinara.interaction.commands.choice; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; 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 index 66ab699..015510c 100644 --- 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 @@ -1,6 +1,6 @@ package net.tomatentum.marinara.test.discord4j; -import net.tomatentum.marinara.interaction.commands.ChoiceValueProvider; +import net.tomatentum.marinara.interaction.commands.choice.ChoiceValueProvider; public enum TestChoiceEnum implements ChoiceValueProvider { TestValue("testValue"), diff --git a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestChoiceEnum.java b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestChoiceEnum.java index 1423ef9..955bab9 100644 --- a/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestChoiceEnum.java +++ b/wrapper/javacord/src/test/java/net/tomatentum/marinara/test/javacord/TestChoiceEnum.java @@ -1,6 +1,6 @@ package net.tomatentum.marinara.test.javacord; -import net.tomatentum.marinara.interaction.commands.ChoiceValueProvider; +import net.tomatentum.marinara.interaction.commands.choice.ChoiceValueProvider; public enum TestChoiceEnum implements ChoiceValueProvider { TestValue("testValue"), -- 2.47.2 From 91b1df8d5bdbe972a38ad2527f367550a425ef9a Mon Sep 17 00:00:00 2001 From: tueem Date: Mon, 3 Mar 2025 12:38:48 +0100 Subject: [PATCH 05/22] replace ExecutableCommandDefinition with InteractionIdentifiers --- .gitignore | 1 + .../commands/CommandConverter.java | 2 +- .../ExecutableSlashCommandDefinition.java | 95 ----------- .../commands/SlashCommandDefinition.java | 146 ++++++++-------- .../ident/InteractionIdentifier.java | 158 ++++++++++++++++++ .../ident/RootCommandIdentifier.java | 93 +++++++++++ .../ident/SlashCommandIdentifier.java | 83 +++++++++ .../AutoCompleteInteractionMethod.java | 21 +-- .../methods/ButtonInteractionMethod.java | 18 +- .../methods/InteractionMethod.java | 23 ++- .../SlashCommandInteractionMethod.java | 30 +--- .../marinara/parser/SlashCommandParser.java | 39 +++-- .../marinara/registry/InteractionEntry.java | 65 +++++++ .../registry/InteractionRegistry.java | 57 ++++--- .../marinara/wrapper/LibraryWrapper.java | 9 +- .../wrapper/discord4j/Discord4JWrapper.java | 84 ++++------ .../wrapper/javacord/JavacordWrapper.java | 90 +++++----- 17 files changed, 655 insertions(+), 359 deletions(-) delete mode 100644 lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/registry/InteractionEntry.java diff --git a/.gitignore b/.gitignore index d11a53b..1dffc61 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ build .vscode lib/bin wrapper/javacord/bin +wrapper/discord4j/bin diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java index fcbfb85..cd90895 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java @@ -12,7 +12,7 @@ public class CommandConverter { return null; } - public interface Spec { + public static interface Spec { public A convertCommand(SlashCommandDefinition def); public O convertSubCommand(SubCommand def, O[] options); diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java deleted file mode 100644 index 480d363..0000000 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java +++ /dev/null @@ -1,95 +0,0 @@ -package net.tomatentum.marinara.interaction.commands; - -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.interaction.commands.annotation.SlashCommandOption.PlaceHolderEnum; -import net.tomatentum.marinara.interaction.commands.choice.EnumChoices; - -public record ExecutableSlashCommandDefinition( - SlashCommand applicationCommand, - SubCommand subCommand, - SubCommandGroup subCommandGroup, - SlashCommandOption[] options) { - - public static SlashCommandOptionChoice[] getActualChoices(SlashCommandOption option) { - SlashCommandOptionChoice[] choices = option.choices(); - if (choices.length <= 0 && !option.choiceEnum().equals(PlaceHolderEnum.class)) - choices = EnumChoices.of(option.choiceEnum()).choices(); - return choices; - } - - @Override - public final boolean equals(Object o) { - if (!(o instanceof ExecutableSlashCommandDefinition)) - return false; - ExecutableSlashCommandDefinition other = (ExecutableSlashCommandDefinition) o; - boolean equals = false; - - if (this.applicationCommand() != null && other.applicationCommand() != 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 - public final String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(applicationCommand.name()); - if (subCommandGroup != null && subCommandGroup.name() != null) - builder.append("::").append(subCommandGroup.name()); - if (subCommand != null && subCommand.name() != null) - builder.append("::").append(subCommand.name()); - return builder.toString(); - } - - public boolean isRootCommand() { - return subCommand == null; - } - - public static class Builder { - private SlashCommand applicationCommand; - private SubCommand subCommand; - private SubCommandGroup subCommandGroup; - - public ExecutableSlashCommandDefinition build() { - if (applicationCommand == null) - throw new IllegalArgumentException("applicationCommandName cant be null"); - - return new ExecutableSlashCommandDefinition(applicationCommand, subCommand, subCommandGroup, subCommand != null ? subCommand.options() : applicationCommand.options()); - } - - public void setApplicationCommand(SlashCommand applicationCommand) { - this.applicationCommand = applicationCommand; - } - - public void setSubCommand(SubCommand subCommand) { - this.subCommand = subCommand; - } - - public void setSubCommandGroup(SubCommandGroup subCommandGroup) { - this.subCommandGroup = subCommandGroup; - } - - public SlashCommand getApplicationCommand() { - return applicationCommand; - } - - public SubCommand getSubCommand() { - return subCommand; - } - - public SubCommandGroup getSubCommandGroup() { - return subCommandGroup; - } - - } -} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java index 376f7a2..1fb073d 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java @@ -1,100 +1,106 @@ package net.tomatentum.marinara.interaction.commands; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; -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 org.apache.logging.log4j.Logger; + +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption.PlaceHolderEnum; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice; +import net.tomatentum.marinara.interaction.commands.choice.EnumChoices; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; +import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; +import net.tomatentum.marinara.util.LoggerUtil; public class SlashCommandDefinition { - private List executableDefinitons; - private SlashCommand slashCommand; - private boolean isRootCommand; - public SlashCommandDefinition(SlashCommand applicationCommand) { - this.executableDefinitons = new ArrayList<>(); - this.slashCommand = applicationCommand; + public static SlashCommandOptionChoice[] getActualChoices(SlashCommandOption option) { + SlashCommandOptionChoice[] choices = option.choices(); + if (choices.length <= 0 && !option.choiceEnum().equals(PlaceHolderEnum.class)) + choices = EnumChoices.of(option.choiceEnum()).choices(); + return choices; } - public SlashCommandDefinition addExecutableCommand(ExecutableSlashCommandDefinition def) { - if (def.applicationCommand() != null) { - if (slashCommand == null) - this.slashCommand = def.applicationCommand(); - if (!this.slashCommand.name().equals(def.applicationCommand().name())) - throw new IllegalArgumentException(def + ": has a non matching Application Command description. Please edit it to equal all other descriptions or remove it to use other definitions descriptions"); - } + private Set entries; + private RootCommandIdentifier rootIdentifier; + private boolean isRootCommand; - if (executableDefinitons.isEmpty()) - this.isRootCommand = def.isRootCommand(); + private Logger logger = LoggerUtil.getLogger(getClass()); - if ((isRootCommand && !def.isRootCommand()) || (!isRootCommand && def.isRootCommand())) { - throw new IllegalArgumentException(def + ": cannot have subcommands and rootcommand definitions together"); + public SlashCommandDefinition(RootCommandIdentifier rootIdentifier) { + this.entries = new HashSet<>(); + this.rootIdentifier = rootIdentifier; + this.isRootCommand = false; + } + + public SlashCommandDefinition addIdentifier(InteractionIdentifier identifier) { + RootCommandIdentifier rootIdentifier = (RootCommandIdentifier) identifier.rootNode(); + + if (!this.rootIdentifier.equals(rootIdentifier)) + throw new IllegalArgumentException("Root Node did not match."); + + if (this.rootIdentifier.description() == null) + this.rootIdentifier = rootIdentifier; + + if (!isRootCommand) + this.isRootCommand = identifier.parent() == null ? true : false; + + if ((isRootCommand && identifier.parent() != null) || (!isRootCommand && identifier.parent() == null)) { + throw new IllegalArgumentException(identifier.toString() + ": cannot have subcommands and rootcommand definitions together"); } - executableDefinitons.add(def); + entries.add(identifier); + this.logger.debug("Added identifer {} to command {}", identifier, rootIdentifier); return this; } - public SubCommandGroup[] getSubCommandGroups() { - List subCommandGroups = Arrays.stream(getExecutableDefinitons()) - .filter((x) -> x.subCommandGroup() != null) - .map((x) -> x.subCommandGroup()) + public SlashCommandIdentifier[] getSubCommandGroups() { + if (isRootCommand) + return null; + + List subCommandGroups = entries().stream() + .filter(x -> x.parent().parent() != null) + .map(x -> x.parent()) .toList(); - HashMap subCommandGroupMap = new HashMap<>(); - subCommandGroups.forEach((x) -> { - SubCommandGroup current = subCommandGroupMap.get(x.name()); - if (current == null || (current.description().isBlank() && !x.description().isBlank())) - subCommandGroupMap.put(x.name(), x); - }); - - return subCommandGroupMap.values().toArray(SubCommandGroup[]::new); + return InteractionIdentifier.distinct(subCommandGroups).toArray(SlashCommandIdentifier[]::new); } - public SubCommand[] getSubCommands() { - List subCommands; - subCommands = Arrays.stream(getExecutableDefinitons()) - .filter((x) -> x.subCommandGroup() == null && x.subCommand() != null) - .map((x) -> x.subCommand()) - .toList(); - - - HashMap subCommandMap = new HashMap<>(); - subCommands.forEach((x) -> { - SubCommand current = subCommandMap.get(x.name()); - if (current == null || (current.description().isBlank() && !x.description().isBlank())) - subCommandMap.put(x.name(), x); - }); - - return subCommandMap.values().toArray(SubCommand[]::new); + public SlashCommandIdentifier[] getSubCommands() { + if (isRootCommand) + return null; + return InteractionIdentifier.distinct(entries.stream().toList()).toArray(SlashCommandIdentifier[]::new); } - public SubCommand[] getSubCommands(String groupName) { - List subCommands; - subCommands = Arrays.stream(getExecutableDefinitons()) - .filter((x) -> x.subCommandGroup().name().equals(groupName) && x.subCommand() != null) - .map((x) -> x.subCommand()) - .toList(); - - HashMap subCommandMap = new HashMap<>(); - subCommands.forEach((x) -> { - SubCommand current = subCommandMap.get(x.name()); - if (current == null || (current.description().isBlank() && !x.description().isBlank())) - subCommandMap.put(x.name(), x); - }); + public SlashCommandIdentifier[] getSubCommands(String groupName) { + if (isRootCommand) + return null; - return subCommandMap.values().toArray(SubCommand[]::new); + List subCommands = entries().stream() + .filter(x -> x.parent().parent() != null && x.parent().name().equals(groupName)) + .map(x -> x.parent().parent()) + .toList(); + + return InteractionIdentifier.distinct(subCommands).toArray(SlashCommandIdentifier[]::new); } - public SlashCommand getSlashCommand() { - return slashCommand; + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SlashCommandDefinition)) + return false; + SlashCommandDefinition other = (SlashCommandDefinition) obj; + return this.rootIdentifier().equals(other.rootIdentifier()); } - public ExecutableSlashCommandDefinition[] getExecutableDefinitons() { - return executableDefinitons.toArray(new ExecutableSlashCommandDefinition[0]); + public Set entries() { + return this.entries; + } + + public RootCommandIdentifier rootIdentifier() { + return rootIdentifier; } public boolean isRootCommand() { diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java new file mode 100644 index 0000000..14a6bfd --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java @@ -0,0 +1,158 @@ +package net.tomatentum.marinara.interaction.ident; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +import net.tomatentum.marinara.interaction.InteractionType; + +public class InteractionIdentifier { + + public static InteractionIdentifier.Builder builder() { + return new InteractionIdentifier.Builder(); + } + + public static RootCommandIdentifier.Builder rootBuilder() { + return new RootCommandIdentifier.Builder(); + } + + public static SlashCommandIdentifier.Builder slashBuilder() { + return new SlashCommandIdentifier.Builder(); + } + + public static InteractionIdentifier createHierarchy(InteractionType type, String... names) { + InteractionIdentifier last = null; + for (String string : names) { + last = builder().name(string).type(type).parent(last).build(); + } + return last; + } + + public static void tryAddDescriptions(InteractionIdentifier receiver, InteractionIdentifier provider) { + if (receiver == null || provider == null) + return; + + if (receiver.description().isBlank()) + receiver.description = provider.description(); + tryAddDescriptions(receiver.parent(), provider.parent()); + } + + /* + * TODO: Might not be the best solution. Propagating to future + * returns only one Identifier per name and takes the first present description + */ + public static Collection distinct(List identifiers) { + HashMap distinctIdentifiers = new HashMap<>(); + identifiers.forEach((x) -> { + InteractionIdentifier current = distinctIdentifiers.get(x.name()); + if (current == null || (current.description().isBlank() && !x.description().isBlank())) + distinctIdentifiers.put(x.name(), x); + }); + return distinctIdentifiers.values(); + } + + private InteractionIdentifier parent; + private String name; + private String description; + private InteractionType type; + + InteractionIdentifier(InteractionIdentifier parent, String name, String description, InteractionType type) { + this.parent = parent; + this.name = name; + this.description = description; + this.type = type; + } + + public InteractionIdentifier rootNode() { return rootNode(this); } + + private InteractionIdentifier rootNode(InteractionIdentifier identifier) { + if (identifier.parent() == null) + return identifier; + return rootNode(identifier.parent()); + } + + public String name() { + return name; + } + + public String description() { + return description; + } + + public InteractionIdentifier parent() { + return parent; + } + + public InteractionType type() { + return type; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof InteractionIdentifier)) + return false; + InteractionIdentifier ident = (InteractionIdentifier) obj; + if (!type().equals(ident.type())) + return false; + if (!name().equals(ident.name())) + return false; + return Objects.equals(ident, obj); + } + + @Override + public String toString() { + if (parent() == null) + return name(); + return "{}.{}".formatted(name(), parent().toString()); + } + + public static class Builder { + private InteractionIdentifier parent; + private String name; + private String description; + private InteractionType type; + + public InteractionIdentifier parent() { + return parent; + } + + public Builder parent(InteractionIdentifier parent) { + this.parent = parent; + return this; + } + + public String name() { + return name; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public String description() { + return description; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public InteractionType type() { + return type; + } + + public Builder type(InteractionType type) { + this.type = type; + return this; + } + + public InteractionIdentifier build() { + return new InteractionIdentifier(parent, name, description, type); + } + + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java new file mode 100644 index 0000000..d32a6a7 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java @@ -0,0 +1,93 @@ +package net.tomatentum.marinara.interaction.ident; + +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; + +public class RootCommandIdentifier extends SlashCommandIdentifier { + + private long[] serverIds; + + public RootCommandIdentifier( + InteractionIdentifier parent, + String name, + String description, + SlashCommandOption[] options, + boolean isAutocomplete, + long[] serverIds) { + super(parent, name, description, options, isAutocomplete); + this.serverIds = serverIds; + } + + public long[] serverIds() { + return serverIds; + } + + public static class Builder { + private InteractionIdentifier parent; + private String name; + private String description; + private SlashCommandOption[] options; + private boolean isAutocomplete = false; + private long[] serverIds; + + + public InteractionIdentifier parent() { + return parent; + } + + public Builder parent(InteractionIdentifier parent) { + this.parent = parent; + return this; + } + + public String name() { + return name; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public String description() { + return this.description; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public SlashCommandOption[] options() { + return this.options; + } + + public Builder options(SlashCommandOption[] options) { + this.options = options; + return this; + } + + public boolean autocomplete() { + return this.isAutocomplete; + } + + public Builder autocomplete(boolean isAutocomplete) { + this.isAutocomplete = isAutocomplete; + return this; + } + + public long[] serverIds() { + return this.serverIds; + } + + public Builder serverIds(long[] serverIds) { + this.serverIds = serverIds; + return this; + } + + public SlashCommandIdentifier build() { + return new RootCommandIdentifier(parent, name, description, options, isAutocomplete, serverIds); + } + + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java new file mode 100644 index 0000000..8ecad75 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java @@ -0,0 +1,83 @@ +package net.tomatentum.marinara.interaction.ident; + +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; + +public class SlashCommandIdentifier extends InteractionIdentifier { + + private SlashCommandOption[] options; + + protected SlashCommandIdentifier( + InteractionIdentifier parent, + String name, + String description, + SlashCommandOption[] options, + boolean isAutocomplete + ) { + super(parent, name, description, isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND); + this.options = options; + } + + public SlashCommandOption[] options() { + return this.options; + } + + public static class Builder { + private InteractionIdentifier parent; + private String name; + private String description; + private SlashCommandOption[] options; + private boolean isAutocomplete = false; + + public InteractionIdentifier parent() { + return parent; + } + + public Builder parent(InteractionIdentifier parent) { + this.parent = parent; + return this; + } + + public String name() { + return name; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public String description() { + return this.description; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public SlashCommandOption[] options() { + return this.options; + } + + public Builder options(SlashCommandOption[] options) { + this.options = options; + return this; + } + + public boolean autocomplete() { + return this.isAutocomplete; + } + + public Builder autocomplete(boolean isAutocomplete) { + this.isAutocomplete = isAutocomplete; + return this; + } + + public SlashCommandIdentifier build() { + return new SlashCommandIdentifier(parent, name, description, options, isAutocomplete); + } + + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java index ffed507..fc08e4d 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java @@ -4,14 +4,13 @@ import java.lang.reflect.Method; import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.interaction.InteractionHandler; -import net.tomatentum.marinara.interaction.InteractionType; -import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.parser.AnnotationParser; import net.tomatentum.marinara.parser.SlashCommandParser; public class AutoCompleteInteractionMethod extends InteractionMethod { - private ExecutableSlashCommandDefinition commandDefinition; + private InteractionIdentifier interactionIdentifier; public AutoCompleteInteractionMethod(Method method, InteractionHandler handler, @@ -21,15 +20,15 @@ public class AutoCompleteInteractionMethod extends InteractionMethod { } @Override - public AnnotationParser[] getParsers() { + public AnnotationParser[] parsers() { return new AnnotationParser[] { - new SlashCommandParser(method, (x) -> { this.commandDefinition = x; } ) + new SlashCommandParser(method, true, (x) -> { this.interactionIdentifier = x; } ) }; } @Override public Object getParameter(Object context, int index) { - Class type = getMethod().getParameterTypes()[index+1]; + Class type = method().getParameterTypes()[index+1]; Object autocompleteOptionValue = marinara.getWrapper().getContextObjectProvider().getAutocompleteFocusedOption(context); if (autocompleteOptionValue != null) return autocompleteOptionValue; @@ -38,14 +37,8 @@ public class AutoCompleteInteractionMethod extends InteractionMethod { } @Override - public boolean canRun(Object context) { - ExecutableSlashCommandDefinition other = marinara.getWrapper().getCommandDefinition(context); - return commandDefinition.equals(other); - } - - @Override - public InteractionType getType() { - return InteractionType.AUTOCOMPLETE; + public InteractionIdentifier identifier() { + return interactionIdentifier; } } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/ButtonInteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/ButtonInteractionMethod.java index fe039ac..ec011a4 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/ButtonInteractionMethod.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/ButtonInteractionMethod.java @@ -5,6 +5,7 @@ import java.lang.reflect.Method; import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.parser.AnnotationParser; import net.tomatentum.marinara.parser.ButtonParser; @@ -17,7 +18,7 @@ public class ButtonInteractionMethod extends InteractionMethod { } @Override - public AnnotationParser[] getParsers() { + public AnnotationParser[] parsers() { return new AnnotationParser[] { new ButtonParser(method, (x) -> { this.customId = x; } ) }; @@ -25,18 +26,17 @@ public class ButtonInteractionMethod extends InteractionMethod { @Override public Object getParameter(Object context, int index) { - Class type = getMethod().getParameterTypes()[index+1]; + Class type = method().getParameterTypes()[index+1]; return marinara.getWrapper().getContextObjectProvider().getComponentContextObject(context, type); } @Override - public boolean canRun(Object context) { - return marinara.getWrapper().getButtonId(context).equals(customId); + public InteractionIdentifier identifier() { + return InteractionIdentifier.builder() + .name(customId) + .description("Button") + .type(InteractionType.BUTTON) + .build(); } - @Override - public InteractionType getType() { - return InteractionType.BUTTON; - } - } 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 ddc3618..09d7c61 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 @@ -12,11 +12,11 @@ import org.apache.logging.log4j.Logger; import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.checks.AppliedCheck; import net.tomatentum.marinara.interaction.InteractionHandler; -import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.annotation.AutoComplete; import net.tomatentum.marinara.interaction.annotation.Button; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.parser.AnnotationParser; import net.tomatentum.marinara.parser.InteractionCheckParser; import net.tomatentum.marinara.util.LoggerUtil; @@ -42,7 +42,8 @@ public abstract class InteractionMethod { private Logger logger = LoggerUtil.getLogger(getClass()); - protected InteractionMethod(Method method, + protected InteractionMethod( + Method method, InteractionHandler handler, Marinara marinara ) { @@ -52,7 +53,7 @@ public abstract class InteractionMethod { this.method = method; this.handler = handler; this.marinara = marinara; - this.parsers = new ArrayList<>(Arrays.asList(getParsers())); + this.parsers = new ArrayList<>(Arrays.asList(parsers())); this.appliedChecks = new ArrayList<>(); parsers.add(new InteractionCheckParser(method, appliedChecks::add, marinara.getCheckRegistry())); @@ -60,14 +61,6 @@ public abstract class InteractionMethod { parsers.stream().forEach(AnnotationParser::parse); } - public abstract AnnotationParser[] getParsers(); - - public abstract Object getParameter(Object context, int index); - - public abstract boolean canRun(Object context); - - public abstract InteractionType getType(); - public void run(Object context) { if (this.appliedChecks.stream().filter(x -> !x.pre(context)).count() > 0) return; @@ -82,7 +75,13 @@ public abstract class InteractionMethod { this.appliedChecks.forEach(x -> x.post(context)); } - public Method getMethod() { + public abstract AnnotationParser[] parsers(); + + public abstract Object getParameter(Object context, int index); + + public abstract InteractionIdentifier identifier(); + + public Method method() { return method; } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/SlashCommandInteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/SlashCommandInteractionMethod.java index 2f5faf4..d89d709 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/SlashCommandInteractionMethod.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/SlashCommandInteractionMethod.java @@ -4,48 +4,34 @@ import java.lang.reflect.Method; import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.interaction.InteractionHandler; -import net.tomatentum.marinara.interaction.InteractionType; -import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.parser.AnnotationParser; import net.tomatentum.marinara.parser.SlashCommandParser; public class SlashCommandInteractionMethod extends InteractionMethod { - private ExecutableSlashCommandDefinition commandDefinition; + private SlashCommandIdentifier interactionIdentifier; SlashCommandInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) { super(method, handler, marinara); } @Override - public AnnotationParser[] getParsers() { + public AnnotationParser[] parsers() { return new AnnotationParser[] { - new SlashCommandParser(method, (x) -> { this.commandDefinition = x; } ) + new SlashCommandParser(method, false, (x) -> { this.interactionIdentifier = x; } ) }; } @Override public Object getParameter(Object context, int index) { - return marinara.getWrapper().getContextObjectProvider().convertCommandOption(context, commandDefinition.options()[index].name()); + return marinara.getWrapper().getContextObjectProvider().convertCommandOption(context, interactionIdentifier.options()[index].name()); } @Override - public boolean canRun(Object context) { - ExecutableSlashCommandDefinition other = marinara.getWrapper().getCommandDefinition(context); - return commandDefinition.equals(other); - } - - @Override - public InteractionType getType() { - return InteractionType.COMMAND; - } - - public ExecutableSlashCommandDefinition getCommandDefinition() { - return commandDefinition; - } - - public void setCommandDefinition(ExecutableSlashCommandDefinition commandDefinition) { - this.commandDefinition = commandDefinition; + public InteractionIdentifier identifier() { + return interactionIdentifier; } } diff --git a/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java b/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java index cf2a244..0cd7072 100644 --- a/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java +++ b/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java @@ -5,22 +5,26 @@ import java.util.function.Consumer; import org.apache.logging.log4j.Logger; -import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; +import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand; import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.util.ReflectionUtil; public class SlashCommandParser implements AnnotationParser { private Method method; - private Consumer consumer; + private boolean isAutoComplete; + private Consumer consumer; private Logger logger = LoggerUtil.getLogger(getClass()); - public SlashCommandParser(Method method, Consumer consumer) { + public SlashCommandParser(Method method, boolean isAutoComplete, Consumer consumer) { this.method = method; + this.isAutoComplete = isAutoComplete; this.consumer = consumer; } @@ -29,23 +33,36 @@ public class SlashCommandParser implements AnnotationParser { this.checkValidCommandMethod(method); SlashCommand cmd = ReflectionUtil.getAnnotation(method, SlashCommand.class); - ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder(); - builder.setApplicationCommand(cmd); + InteractionIdentifier lastIdentifier = InteractionIdentifier.rootBuilder() + .name(cmd.name()) + .description(cmd.description()) + .options(cmd.options()) + .autocomplete(isAutoComplete) + .serverIds(cmd.serverIds()) + .build(); if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) { SubCommandGroup cmdGroup = ReflectionUtil.getAnnotation(method, SubCommandGroup.class); - builder.setSubCommandGroup(cmdGroup); + lastIdentifier = InteractionIdentifier.builder() + .name(cmdGroup.name()) + .description(cmdGroup.description()) + .type(isAutoComplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND) + .parent(lastIdentifier) + .build(); } if (ReflectionUtil.isAnnotationPresent(method, SubCommand.class)) { SubCommand subCmd = ReflectionUtil.getAnnotation(method, SubCommand.class); - builder.setSubCommand(subCmd); + lastIdentifier = InteractionIdentifier.slashBuilder() + .name(subCmd.name()) + .description(subCmd.description()) + .options(subCmd.options()) + .autocomplete(isAutoComplete) + .build(); } - ExecutableSlashCommandDefinition def = builder.build(); - - logger.trace("Parsed using SlashCommandParser for method {} with the result:\n{}", ReflectionUtil.getFullMethodName(method), def.toString()); - consumer.accept(builder.build()); + logger.trace("Parsed using SlashCommandParser for method {} with the result:\n{}", ReflectionUtil.getFullMethodName(method), lastIdentifier.toString()); + consumer.accept((SlashCommandIdentifier) lastIdentifier); } @Override diff --git a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionEntry.java b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionEntry.java new file mode 100644 index 0000000..6e2735b --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionEntry.java @@ -0,0 +1,65 @@ +package net.tomatentum.marinara.registry; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.logging.log4j.Logger; + +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.methods.InteractionMethod; +import net.tomatentum.marinara.util.LoggerUtil; + +public class InteractionEntry { + private InteractionIdentifier identifier; + private Set methods; + + private Logger logger = LoggerUtil.getLogger(getClass()); + + public InteractionEntry(InteractionIdentifier identifier) { + this.identifier = identifier; + this.methods = new HashSet<>(); + } + + public InteractionEntry addMethod(InteractionMethod method) { + if (!method.identifier().equals(this.identifier)) + throw new IllegalArgumentException("Method's identifier did not match the entry's identifier"); + + this.methods.add(method); + InteractionIdentifier.tryAddDescriptions(identifier, method.identifier()); + return this; + } + + public void runAll(Object context) { + this.methods.stream().forEach(x -> { + logger.debug("Running Method {} from {} with context {}", x.toString(), this.toString(), context.toString()); + x.run(context); + }); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof InteractionEntry)) + return false; + InteractionEntry other = (InteractionEntry) obj; + return other.identifier().equals(identifier()); + } + + @Override + public String toString() { + return "InteractionEntry(%s)".formatted(identifier().toString()); + } + + public InteractionType type() { + return identifier().type(); + } + + public InteractionIdentifier identifier() { + return identifier; + } + + public Set methods() { + return methods; + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java index 27a2152..59d01b7 100644 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java +++ b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java @@ -2,8 +2,10 @@ package net.tomatentum.marinara.registry; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import org.apache.logging.log4j.Logger; @@ -11,28 +13,36 @@ import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; -import net.tomatentum.marinara.interaction.methods.SlashCommandInteractionMethod; +import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; +import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.util.LoggerUtil; +import net.tomatentum.marinara.wrapper.LibraryWrapper; import net.tomatentum.marinara.interaction.methods.InteractionMethod; public class InteractionRegistry { private Logger logger = LoggerUtil.getLogger(getClass()); - private List interactionMethods; + private Set interactions; private Marinara marinara; public InteractionRegistry(Marinara marinara) { - this.interactionMethods = new ArrayList<>(); + this.interactions = new HashSet<>(); this.marinara = marinara; marinara.getWrapper().subscribeInteractions(this::handle); } + /* + * TODO: Maybe relocate InteractionEntry checking to another class with description merging. + */ public void addInteractions(InteractionHandler interactionHandler) { for (Method method : interactionHandler.getClass().getMethods()) { InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, marinara); if (iMethod != null) { - this.interactionMethods.add(iMethod); - logger.debug("Added {} method from {}", iMethod.getMethod().getName(), interactionHandler.getClass().getSimpleName()); + Optional entry = this.interactions.stream().filter(iMethod::equals).findFirst(); + if (entry.isEmpty()) { + interactions.add(new InteractionEntry(iMethod.identifier()).addMethod(iMethod)); + }else + entry.get().addMethod(iMethod); + logger.debug("Added {} method from {}", iMethod.method().getName(), interactionHandler.getClass().getSimpleName()); } } logger.info("Added all Interactions from {}", interactionHandler.getClass().getSimpleName()); @@ -40,25 +50,22 @@ public class InteractionRegistry { public void registerCommands() { List defs = new ArrayList<>(); - List execDefs = interactionMethods.stream() - .filter((x) -> x.getClass().isAssignableFrom(SlashCommandInteractionMethod.class)) - .map((x) -> ((SlashCommandInteractionMethod)x).getCommandDefinition()) + List slashIdentifiers = interactions.stream() + .filter((x) -> x.type().equals(InteractionType.COMMAND)) + .map((x) -> (SlashCommandIdentifier)x.identifier()) .toList(); - execDefs.forEach((def) -> { + slashIdentifiers.forEach((ident) -> { Optional appDef = defs.stream() - .filter((x) -> x.getSlashCommand().equals(def.applicationCommand())) + .filter((x) -> x.rootIdentifier().equals(ident.rootNode())) .findFirst(); - if (appDef.isPresent()) - appDef.get().addExecutableCommand(def); - else - defs.add(new SlashCommandDefinition(def.applicationCommand()).addExecutableCommand(def)); - logger.debug("Added Executable Command {}{}{} for registration", - def.applicationCommand().name(), - def.subCommandGroup() == null ? "" : "." + def.subCommandGroup().name(), - def.subCommand() == null ? "" : "." + def.subCommand().name() - ); + if (appDef.isPresent()) + appDef.get().addIdentifier(ident); + else + defs.add( + new SlashCommandDefinition((RootCommandIdentifier) ident.rootNode()) + .addIdentifier(ident)); }); marinara.getWrapper().registerSlashCommands(defs.toArray(SlashCommandDefinition[]::new)); @@ -66,12 +73,12 @@ public class InteractionRegistry { } public void handle(Object context) { - InteractionType type = marinara.getWrapper().getInteractionType(context); logger.debug("Received {} interaction ", context); - interactionMethods.forEach((m) -> { - if (m.getType().equals(type) && m.canRun(context)) { - logger.info("Running {} interaction using {}\ncontext: {}", type, m.getMethod().toString(), context.toString()); - m.run(context); + LibraryWrapper wrapper = marinara.getWrapper(); + interactions.forEach((e) -> { + if (wrapper.getInteractionIdentifier(context).equals(e.identifier())) { + logger.info("Running {} interaction using {}\ncontext: {}", e.type(), e.toString(), context.toString()); + e.runAll(context); } }); } diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java index 7bf932a..0a4ede7 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java @@ -5,8 +5,7 @@ import java.util.List; import java.util.function.Consumer; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition; -import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; public abstract class LibraryWrapper { @@ -27,12 +26,8 @@ public abstract class LibraryWrapper { interactionSubscriber.remove(consumer); } - public abstract InteractionType getInteractionType(Object context); - public abstract void registerSlashCommands(SlashCommandDefinition[] defs); - public abstract ExecutableSlashCommandDefinition getCommandDefinition(Object context); - - public abstract String getButtonId(Object context); + public abstract InteractionIdentifier getInteractionIdentifier(Object context); public abstract ContextObjectProvider getContextObjectProvider(); diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java index b5f7f73..7c046b3 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -4,7 +4,6 @@ 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; @@ -20,16 +19,13 @@ 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.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; +import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.wrapper.LibraryWrapper; @@ -63,18 +59,6 @@ public class Discord4JWrapper extends LibraryWrapper { 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<>(); @@ -83,8 +67,8 @@ public class Discord4JWrapper extends LibraryWrapper { for (SlashCommandDefinition slashCommandDefinition : defs) { ApplicationCommandRequest request = convertSlashCommand(slashCommandDefinition); - if (slashCommandDefinition.getSlashCommand().serverIds().length > 0) { - for (long serverId : slashCommandDefinition.getSlashCommand().serverIds()) { + if (slashCommandDefinition.rootIdentifier().serverIds().length > 0) { + for (long serverId : slashCommandDefinition.rootIdentifier().serverIds()) { serverCommands.putIfAbsent(serverId, new ArrayList<>()); serverCommands.get(serverId).add(request); } @@ -99,9 +83,16 @@ public class Discord4JWrapper extends LibraryWrapper { } @Override - public ExecutableSlashCommandDefinition getCommandDefinition(Object context) { + public InteractionIdentifier getInteractionIdentifier(Object context) { + + if (context instanceof ButtonInteractionEvent) { + ButtonInteractionEvent interaction = (ButtonInteractionEvent) context; + return InteractionIdentifier.builder().name(interaction.getCustomId()).type(InteractionType.BUTTON).build(); + } + List options; String commandName; + boolean isAutocomplete = false; if (context instanceof ChatInputInteractionEvent) { ChatInputInteractionEvent interaction = (ChatInputInteractionEvent) context; @@ -111,30 +102,35 @@ public class Discord4JWrapper extends LibraryWrapper { ChatInputAutoCompleteEvent interaction = (ChatInputAutoCompleteEvent) context; options = SUB_FILTER.apply(interaction.getOptions()); commandName = interaction.getCommandName(); + isAutocomplete = true; }else return null; - ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder(); + InteractionIdentifier last = InteractionIdentifier.slashBuilder().name(commandName).autocomplete(isAutocomplete).build(); - 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); + if (!options.isEmpty()) { + List sub_options = SUB_FILTER.apply(options.getFirst().getOptions()); + if (!sub_options.isEmpty()) { + last = InteractionIdentifier.builder() + .name(options.getFirst().getName()) + .type(isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND) + .parent(last).build(); + last = InteractionIdentifier.slashBuilder() + .name(sub_options.getFirst().getName()) + .autocomplete(isAutocomplete) + .parent(last).build(); + }else + last = InteractionIdentifier.slashBuilder() + .name(options.getFirst().getName()) + .autocomplete(isAutocomplete) + .parent(last).build(); } - - return builder.build(); + return last; } private ApplicationCommandRequest convertSlashCommand(SlashCommandDefinition def) { List options = new ArrayList<>(); - SlashCommand cmd = def.getSlashCommand(); + RootCommandIdentifier cmd = def.rootIdentifier(); 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); @@ -149,8 +145,8 @@ public class Discord4JWrapper extends LibraryWrapper { .build(); } - private ApplicationCommandOptionData convertSubCommandGroupDef(SlashCommandDefinition def, SubCommandGroup subGroup) { - SubCommand[] subCommands = def.getSubCommands(subGroup.name()); + private ApplicationCommandOptionData convertSubCommandGroupDef(SlashCommandDefinition def, SlashCommandIdentifier subGroup) { + SlashCommandIdentifier[] subCommands = def.getSubCommands(subGroup.name()); List convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommandDef).toList(); return ApplicationCommandOptionData.builder() .type(Type.SUB_COMMAND_GROUP.getValue()) @@ -160,7 +156,7 @@ public class Discord4JWrapper extends LibraryWrapper { .build(); } - private ApplicationCommandOptionData convertSubCommandDef(SubCommand sub) { + private ApplicationCommandOptionData convertSubCommandDef(SlashCommandIdentifier sub) { List convertedOptions = Arrays.stream(sub.options()).map(this::convertOptionDef).toList(); return ApplicationCommandOptionData.builder() .type(Type.SUB_COMMAND_GROUP.getValue()) @@ -184,7 +180,7 @@ public class Discord4JWrapper extends LibraryWrapper { private List convertChoices(SlashCommandOption option) { List convertedChoices = new ArrayList<>(); - for (SlashCommandOptionChoice choice : ExecutableSlashCommandDefinition.getActualChoices(option)) { + for (SlashCommandOptionChoice choice : SlashCommandDefinition.getActualChoices(option)) { var builder = ApplicationCommandOptionChoiceData.builder(); builder.name(choice.name()); if (choice.longValue() != Long.MAX_VALUE) @@ -198,12 +194,6 @@ public class Discord4JWrapper extends LibraryWrapper { 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/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 38d0d55..6c1932d 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 @@ -5,12 +5,10 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import org.apache.logging.log4j.Logger; import org.javacord.api.DiscordApi; -import org.javacord.api.interaction.ApplicationCommandInteraction; import org.javacord.api.interaction.AutocompleteInteraction; import org.javacord.api.interaction.ButtonInteraction; import org.javacord.api.interaction.SlashCommandBuilder; @@ -20,16 +18,13 @@ import org.javacord.api.interaction.SlashCommandOptionBuilder; import org.javacord.api.interaction.SlashCommandOptionChoiceBuilder; import org.javacord.api.interaction.SlashCommandOptionType; -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.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; +import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.LibraryWrapper; @@ -51,25 +46,14 @@ public class JavacordWrapper extends LibraryWrapper { logger.info("Javacord wrapper loaded!"); } - @Override - public InteractionType getInteractionType(Object context) { - if (AutocompleteInteraction.class.isAssignableFrom(context.getClass())) - return InteractionType.AUTOCOMPLETE; - if (ApplicationCommandInteraction.class.isAssignableFrom(context.getClass())) - return InteractionType.COMMAND; - if (ButtonInteraction.class.isAssignableFrom(context.getClass())) - return InteractionType.BUTTON; - return null; - } - @Override public void registerSlashCommands(SlashCommandDefinition[] defs) { HashMap> serverCommands = new HashMap<>(); Set globalCommands = new HashSet<>(); for (SlashCommandDefinition slashCommandDefinition : defs) { SlashCommandBuilder builder = convertSlashCommand(slashCommandDefinition); - if (slashCommandDefinition.getSlashCommand().serverIds().length > 0) { - for (long serverId : slashCommandDefinition.getSlashCommand().serverIds()) { + if (slashCommandDefinition.rootIdentifier().serverIds().length > 0) { + for (long serverId : slashCommandDefinition.rootIdentifier().serverIds()) { serverCommands.putIfAbsent(serverId, new HashSet<>()); serverCommands.get(serverId).add(builder); } @@ -84,32 +68,52 @@ public class JavacordWrapper extends LibraryWrapper { } @Override - public ExecutableSlashCommandDefinition getCommandDefinition(Object context) { + public InteractionIdentifier getInteractionIdentifier(Object context) { + if (context instanceof ButtonInteraction) { + ButtonInteraction button = (ButtonInteraction) context; + return InteractionIdentifier.builder().name(button.getCustomId()).type(InteractionType.BUTTON).build(); + } + if (!(context instanceof SlashCommandInteraction)) return null; + boolean isAutocomplete = false; + + if (context instanceof AutocompleteInteraction) + isAutocomplete = true; + SlashCommandInteraction interaction = (SlashCommandInteraction) context; - ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder(); + InteractionIdentifier lastIdentifier = InteractionIdentifier.rootBuilder() + .name(interaction.getCommandName()) + .autocomplete(isAutocomplete) + .build(); List options = interaction.getOptions(); - try { - builder.setApplicationCommand(TypeFactory.annotation(SlashCommand.class, Map.of("name", interaction.getCommandName()))); - if (!options.isEmpty()) { - if (!options.getFirst().getArguments().isEmpty()) { - builder.setSubCommandGroup(TypeFactory.annotation(SubCommandGroup.class, Map.of("name", options.getFirst().getName()))); - builder.setSubCommand(TypeFactory.annotation(SubCommand.class, Map.of("name", options.getFirst().getOptions().getFirst().getName()))); - }else - builder.setSubCommand(TypeFactory.annotation(SubCommand.class, Map.of("name", options.getFirst().getName()))); - } - } catch (AnnotationFormatException e) { - logger.fatal(e); + if (!options.isEmpty()) { + if (!options.getFirst().getArguments().isEmpty()) { + lastIdentifier = InteractionIdentifier.builder() + .name(options.getFirst().getName()) + .type(isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND) + .parent(lastIdentifier) + .build(); + lastIdentifier = InteractionIdentifier.slashBuilder() + .name(options.getFirst().getOptions().getFirst().getName()) + .autocomplete(isAutocomplete) + .parent(lastIdentifier) + .build(); + }else + lastIdentifier = InteractionIdentifier.slashBuilder() + .name(options.getFirst().getName()) + .autocomplete(isAutocomplete) + .parent(lastIdentifier) + .build(); } - return builder.build(); + return lastIdentifier; } private SlashCommandBuilder convertSlashCommand(SlashCommandDefinition def) { List options = new ArrayList<>(); - SlashCommand cmd = def.getSlashCommand(); + RootCommandIdentifier cmd = def.rootIdentifier(); 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); @@ -120,8 +124,8 @@ public class JavacordWrapper extends LibraryWrapper { return org.javacord.api.interaction.SlashCommand.with(cmd.name(), cmd.description(), options); } - private org.javacord.api.interaction.SlashCommandOption convertSubCommandGroupDef(SlashCommandDefinition def, SubCommandGroup subGroup) { - SubCommand[] subCommands = def.getSubCommands(subGroup.name()); + private org.javacord.api.interaction.SlashCommandOption convertSubCommandGroupDef(SlashCommandDefinition def, SlashCommandIdentifier subGroup) { + SlashCommandIdentifier[] subCommands = def.getSubCommands(subGroup.name()); List convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommandDef).toList(); return org.javacord.api.interaction.SlashCommandOption.createWithOptions( org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND_GROUP, @@ -130,7 +134,7 @@ public class JavacordWrapper extends LibraryWrapper { convertedSubCommands); } - private org.javacord.api.interaction.SlashCommandOption convertSubCommandDef(SubCommand sub) { + private org.javacord.api.interaction.SlashCommandOption convertSubCommandDef(SlashCommandIdentifier sub) { List convertedOptions = Arrays.stream(sub.options()).map(this::convertOptionDef).toList(); return org.javacord.api.interaction.SlashCommandOption.createWithOptions( org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND, @@ -155,7 +159,7 @@ public class JavacordWrapper extends LibraryWrapper { private List convertChoices(SlashCommandOption option) { List convertedChoices = new ArrayList<>(); - for (SlashCommandOptionChoice choice : ExecutableSlashCommandDefinition.getActualChoices(option)) { + for (SlashCommandOptionChoice choice : SlashCommandDefinition.getActualChoices(option)) { SlashCommandOptionChoiceBuilder builder = new SlashCommandOptionChoiceBuilder(); builder.setName(choice.name()); if (choice.longValue() != Long.MAX_VALUE) @@ -172,12 +176,6 @@ public class JavacordWrapper extends LibraryWrapper { return convertedChoices; } - @Override - public String getButtonId(Object context) { - ButtonInteraction button = (ButtonInteraction) context; - return button.getCustomId(); - } - @Override public ContextObjectProvider getContextObjectProvider() { return contextObjectProvider; -- 2.47.2 From 823402e0cdda0d031af733b845056eaa0beb20dd Mon Sep 17 00:00:00 2001 From: Tueem Date: Mon, 3 Mar 2025 23:32:07 +0100 Subject: [PATCH 06/22] fix base getSubCommands method --- .../marinara/interaction/commands/SlashCommandDefinition.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java index 1fb073d..5a2f861 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java @@ -72,7 +72,7 @@ public class SlashCommandDefinition { public SlashCommandIdentifier[] getSubCommands() { if (isRootCommand) return null; - return InteractionIdentifier.distinct(entries.stream().toList()).toArray(SlashCommandIdentifier[]::new); + return InteractionIdentifier.distinct(entries.stream().filter(x -> x instanceof RootCommandIdentifier).toList()).toArray(SlashCommandIdentifier[]::new); } public SlashCommandIdentifier[] getSubCommands(String groupName) { -- 2.47.2 From 56b668851bc0c2425188b2c53529fd85778dc6e7 Mon Sep 17 00:00:00 2001 From: Tueem Date: Mon, 3 Mar 2025 23:32:25 +0100 Subject: [PATCH 07/22] add CommandConverter logic and wrapper implementations --- .../commands/CommandConverter.java | 57 ++++++++++--- .../discord4j/Discord4JConverterSpec.java | 75 +++++++++++++++++ .../wrapper/discord4j/Discord4JWrapper.java | 77 ++--------------- .../javacord/JavacordConverterSpec.java | 73 +++++++++++++++++ .../wrapper/javacord/JavacordWrapper.java | 82 ++----------------- 5 files changed, 207 insertions(+), 157 deletions(-) create mode 100644 wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java create mode 100644 wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java index cd90895..e2f78f2 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java @@ -1,23 +1,60 @@ package net.tomatentum.marinara.interaction.commands; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; -import net.tomatentum.marinara.interaction.commands.annotation.SubCommand; -import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; +import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; -public class CommandConverter { +public class CommandConverter { - private Spec spec; + public static CommandConverter of(Spec spec) { + return new CommandConverter<>(spec); + } + + private Spec spec; + + CommandConverter(Spec spec) { + this.spec = spec; + } public A convert(SlashCommandDefinition def) { - return null; + List options = new ArrayList<>(); + if (!def.isRootCommand()) { + Arrays.stream(def.getSubCommands()).map(this::convertSubCommand).forEach(options::add); + Arrays.stream(def.getSubCommandGroups()).map(x -> this.convertSubCommandGroup(def, x)).forEach(options::add); + }else + Arrays.stream(def.rootIdentifier().options()).map(this::convertOption).forEach(options::add); + + return spec.convertCommand(def.rootIdentifier(), options); + } + + private O convertSubCommandGroup(SlashCommandDefinition def, InteractionIdentifier identifier) { + SlashCommandIdentifier[] subCommands = def.getSubCommands(identifier.name()); + List convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommand).toList(); + return spec.convertSubCommandGroup(identifier, convertedSubCommands); + } + + private O convertSubCommand(SlashCommandIdentifier identifier) { + List options = Arrays.stream(identifier.options()).map(this::convertOption).toList(); + return spec.convertSubCommand(identifier, options); + } + + private O convertOption(SlashCommandOption option) { + List choices = Arrays.stream(SlashCommandDefinition.getActualChoices(option)).map(spec::convertChoice).toList(); + return spec.convertOption(option, choices); } public static interface Spec { - public A convertCommand(SlashCommandDefinition def); - public O convertSubCommand(SubCommand def, O[] options); - public O convertSubCommandGroup(SubCommandGroup def, O[] options); - public O convertOption(SlashCommandOption option, C[] choices); - public C[] convertChoice(SlashCommandOption option); + public A convertCommand(RootCommandIdentifier rootIdentifier, List options); + public O convertSubCommandGroup(InteractionIdentifier identifier, List subCommands); + public O convertSubCommand(InteractionIdentifier identifier, List options); + public O convertOption(SlashCommandOption option, List choices); + public C convertChoice(SlashCommandOptionChoice choice); } } diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java new file mode 100644 index 0000000..6045b94 --- /dev/null +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java @@ -0,0 +1,75 @@ +package net.tomatentum.marinara.wrapper.discord4j; + +import java.util.List; + +import discord4j.core.object.command.ApplicationCommandOption.Type; +import discord4j.discordjson.json.ApplicationCommandOptionChoiceData; +import discord4j.discordjson.json.ApplicationCommandOptionData; +import discord4j.discordjson.json.ApplicationCommandRequest; +import net.tomatentum.marinara.interaction.commands.CommandConverter; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; +import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; + +public class Discord4JConverterSpec implements CommandConverter.Spec { + + @Override + public ApplicationCommandRequest convertCommand(RootCommandIdentifier rootIdentifier, + List options) { + return ApplicationCommandRequest.builder() + .name(rootIdentifier.name()) + .description(rootIdentifier.description()) + .options(options) + .build(); + } + + @Override + public ApplicationCommandOptionData convertSubCommandGroup(InteractionIdentifier identifier, + List subCommands) { + return ApplicationCommandOptionData.builder() + .type(Type.SUB_COMMAND_GROUP.getValue()) + .name(identifier.name()) + .description(identifier.description()) + .options(subCommands) + .build(); + } + + @Override + public ApplicationCommandOptionData convertSubCommand(InteractionIdentifier identifier, + List options) { + return ApplicationCommandOptionData.builder() + .type(Type.SUB_COMMAND_GROUP.getValue()) + .name(identifier.name()) + .description(identifier.description()) + .options(options) + .build(); + } + + @Override + public ApplicationCommandOptionData convertOption(SlashCommandOption option, + List choices) { + Type type = Type.of(option.type().getValue()); + return ApplicationCommandOptionData.builder() + .type(type.getValue()) + .name(option.name()) + .description(option.description()) + .required(option.required()) + .autocomplete(option.autocomplete()) + .choices(choices) + .build(); + } + + @Override + public ApplicationCommandOptionChoiceData convertChoice(SlashCommandOptionChoice choice) { + var builder = ApplicationCommandOptionChoiceData.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 builder.build(); + } + +} diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java index 7c046b3..85a1e28 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -1,7 +1,6 @@ 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.function.Function; @@ -20,12 +19,9 @@ import discord4j.discordjson.json.ApplicationCommandOptionData; import discord4j.discordjson.json.ApplicationCommandRequest; import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.commands.CommandConverter; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; -import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; -import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.wrapper.LibraryWrapper; @@ -44,12 +40,15 @@ public class Discord4JWrapper extends LibraryWrapper { private GatewayDiscordClient api; private Discord4JContextObjectProvider contextObjectProvider; + private CommandConverter commandConverter; private Logger logger = LoggerUtil.getLogger(getClass()); public Discord4JWrapper(GatewayDiscordClient api) { this.api = api; this.contextObjectProvider = new Discord4JContextObjectProvider(); + this.commandConverter = CommandConverter.of(new Discord4JConverterSpec()); + if (api != null) api.on(InteractionCreateEvent.class) .subscribe(event -> handleInteraction(event)); @@ -66,7 +65,7 @@ public class Discord4JWrapper extends LibraryWrapper { long applicationId = api.getRestClient().getApplicationId().block(); for (SlashCommandDefinition slashCommandDefinition : defs) { - ApplicationCommandRequest request = convertSlashCommand(slashCommandDefinition); + ApplicationCommandRequest request = this.commandConverter.convert(slashCommandDefinition); if (slashCommandDefinition.rootIdentifier().serverIds().length > 0) { for (long serverId : slashCommandDefinition.rootIdentifier().serverIds()) { serverCommands.putIfAbsent(serverId, new ArrayList<>()); @@ -128,72 +127,6 @@ public class Discord4JWrapper extends LibraryWrapper { return last; } - private ApplicationCommandRequest convertSlashCommand(SlashCommandDefinition def) { - List options = new ArrayList<>(); - RootCommandIdentifier cmd = def.rootIdentifier(); - 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, SlashCommandIdentifier subGroup) { - SlashCommandIdentifier[] 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(SlashCommandIdentifier 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 : SlashCommandDefinition.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()); - convertedChoices.add(builder.build()); - } - return convertedChoices; - } - @Override public ContextObjectProvider getContextObjectProvider() { return this.contextObjectProvider; diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java new file mode 100644 index 0000000..e2748a1 --- /dev/null +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java @@ -0,0 +1,73 @@ +package net.tomatentum.marinara.wrapper.javacord; + +import java.util.List; + +import org.javacord.api.interaction.SlashCommand; +import org.javacord.api.interaction.SlashCommandBuilder; +import org.javacord.api.interaction.SlashCommandOption; +import org.javacord.api.interaction.SlashCommandOptionBuilder; +import org.javacord.api.interaction.SlashCommandOptionChoice; +import org.javacord.api.interaction.SlashCommandOptionChoiceBuilder; +import org.javacord.api.interaction.SlashCommandOptionType; + +import net.tomatentum.marinara.interaction.commands.CommandConverter; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; + +public class JavacordConverterSpec implements CommandConverter.Spec { + + @Override + public SlashCommandBuilder convertCommand(RootCommandIdentifier rootIdentifier, List options) { + return SlashCommand.with(rootIdentifier.name(), rootIdentifier.description(), options); + } + + @Override + public SlashCommandOption convertSubCommandGroup(InteractionIdentifier identifier, + List subCommands) { + return SlashCommandOption.createWithOptions( + SlashCommandOptionType.SUB_COMMAND_GROUP, + identifier.name(), + identifier.description(), + subCommands); + } + + @Override + public SlashCommandOption convertSubCommand(InteractionIdentifier identifier, List options) { + return SlashCommandOption.createWithOptions( + SlashCommandOptionType.SUB_COMMAND, + identifier.name(), + identifier.description(), + options); + } + + @Override + public SlashCommandOption convertOption( + net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption option, + List choices) { + SlashCommandOptionType type = SlashCommandOptionType.fromValue(option.type().getValue()); + return new SlashCommandOptionBuilder() + .setType(type) + .setName(option.name()) + .setDescription(option.description()) + .setRequired(option.required()) + .setAutocompletable(option.autocomplete()) + .setChoices(choices) + .build(); + } + + @Override + public SlashCommandOptionChoice convertChoice( + net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice choice) { + SlashCommandOptionChoiceBuilder builder = new SlashCommandOptionChoiceBuilder().setName(choice.name()); + if (choice.longValue() != Long.MAX_VALUE) + builder.setValue(choice.longValue()); + /* + not yet available + if (choice.doubleValue() != Double.MAX_VALUE) + builder.setValue(choice.doubleValue()); + */ + if (!choice.stringValue().isEmpty()) + builder.setValue(choice.stringValue()); + return builder.build(); + } +} diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java index 6c1932d..57e9c64 100644 --- a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java @@ -1,7 +1,5 @@ package net.tomatentum.marinara.wrapper.javacord; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -14,17 +12,13 @@ import org.javacord.api.interaction.ButtonInteraction; import org.javacord.api.interaction.SlashCommandBuilder; import org.javacord.api.interaction.SlashCommandInteraction; import org.javacord.api.interaction.SlashCommandInteractionOption; -import org.javacord.api.interaction.SlashCommandOptionBuilder; -import org.javacord.api.interaction.SlashCommandOptionChoiceBuilder; -import org.javacord.api.interaction.SlashCommandOptionType; +import org.javacord.api.interaction.SlashCommandOption; +import org.javacord.api.interaction.SlashCommandOptionChoice; import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.commands.CommandConverter; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; -import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; -import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; -import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.LibraryWrapper; @@ -33,12 +27,15 @@ public class JavacordWrapper extends LibraryWrapper { private DiscordApi api; private JavacordContextObjectProvider contextObjectProvider; + private CommandConverter commandConverter; private Logger logger = LoggerUtil.getLogger(getClass()); public JavacordWrapper(DiscordApi api) { this.api = api; this.contextObjectProvider = new JavacordContextObjectProvider(); + this.commandConverter = CommandConverter.of(new JavacordConverterSpec()); + if (api != null) api.addInteractionCreateListener((e) -> handleInteraction(e.getInteraction())); else @@ -51,7 +48,7 @@ public class JavacordWrapper extends LibraryWrapper { HashMap> serverCommands = new HashMap<>(); Set globalCommands = new HashSet<>(); for (SlashCommandDefinition slashCommandDefinition : defs) { - SlashCommandBuilder builder = convertSlashCommand(slashCommandDefinition); + SlashCommandBuilder builder = commandConverter.convert(slashCommandDefinition); if (slashCommandDefinition.rootIdentifier().serverIds().length > 0) { for (long serverId : slashCommandDefinition.rootIdentifier().serverIds()) { serverCommands.putIfAbsent(serverId, new HashSet<>()); @@ -111,71 +108,6 @@ public class JavacordWrapper extends LibraryWrapper { return lastIdentifier; } - private SlashCommandBuilder convertSlashCommand(SlashCommandDefinition def) { - List options = new ArrayList<>(); - RootCommandIdentifier cmd = def.rootIdentifier(); - 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 org.javacord.api.interaction.SlashCommand.with(cmd.name(), cmd.description(), options); - } - - private org.javacord.api.interaction.SlashCommandOption convertSubCommandGroupDef(SlashCommandDefinition def, SlashCommandIdentifier subGroup) { - SlashCommandIdentifier[] subCommands = def.getSubCommands(subGroup.name()); - 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(), - convertedSubCommands); - } - - private org.javacord.api.interaction.SlashCommandOption convertSubCommandDef(SlashCommandIdentifier sub) { - 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(), - sub.description(), - convertedOptions); - } - - private org.javacord.api.interaction.SlashCommandOption convertOptionDef(SlashCommandOption option) { - SlashCommandOptionType type = SlashCommandOptionType.fromValue(option.type().getValue()); - SlashCommandOptionBuilder builder = new SlashCommandOptionBuilder(); - builder - .setType(type) - .setName(option.name()) - .setDescription(option.description()) - .setRequired(option.required()) - .setAutocompletable(option.autocomplete()) - .setChoices(convertChoices(option)); - - return builder.build(); - } - - private List convertChoices(SlashCommandOption option) { - List convertedChoices = new ArrayList<>(); - for (SlashCommandOptionChoice choice : SlashCommandDefinition.getActualChoices(option)) { - SlashCommandOptionChoiceBuilder builder = new SlashCommandOptionChoiceBuilder(); - builder.setName(choice.name()); - if (choice.longValue() != Long.MAX_VALUE) - builder.setValue(choice.longValue()); - /* - not yet available - if (choice.doubleValue() != Double.MAX_VALUE) - builder.setValue(choice.doubleValue()); - */ - if (!choice.stringValue().isEmpty()) - builder.setValue(choice.stringValue()); - convertedChoices.add(builder.build()); - } - return convertedChoices; - } - @Override public ContextObjectProvider getContextObjectProvider() { return contextObjectProvider; -- 2.47.2 From f4ee258eb1684acee8de82a2437ff4bf92ad4965 Mon Sep 17 00:00:00 2001 From: Tueem Date: Mon, 3 Mar 2025 23:40:06 +0100 Subject: [PATCH 08/22] remove missing parent() call in SlashCommandDefinition#getSubCommands() --- .../marinara/interaction/commands/SlashCommandDefinition.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java index 5a2f861..a1525c9 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java @@ -72,7 +72,7 @@ public class SlashCommandDefinition { public SlashCommandIdentifier[] getSubCommands() { if (isRootCommand) return null; - return InteractionIdentifier.distinct(entries.stream().filter(x -> x instanceof RootCommandIdentifier).toList()).toArray(SlashCommandIdentifier[]::new); + return InteractionIdentifier.distinct(entries.stream().filter(x -> x.parent() instanceof RootCommandIdentifier).toList()).toArray(SlashCommandIdentifier[]::new); } public SlashCommandIdentifier[] getSubCommands(String groupName) { -- 2.47.2 From f940f48566a945c2a6ec82d8e38eff5e122aaad6 Mon Sep 17 00:00:00 2001 From: tueem Date: Tue, 4 Mar 2025 11:16:44 +0100 Subject: [PATCH 09/22] move CommandConverter to wrapper package --- .../{interaction/commands => wrapper}/CommandConverter.java | 3 ++- .../marinara/wrapper/discord4j/Discord4JConverterSpec.java | 2 +- .../marinara/wrapper/discord4j/Discord4JWrapper.java | 2 +- .../marinara/wrapper/javacord/JavacordConverterSpec.java | 2 +- .../tomatentum/marinara/wrapper/javacord/JavacordWrapper.java | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) rename lib/src/main/java/net/tomatentum/marinara/{interaction/commands => wrapper}/CommandConverter.java (95%) diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandConverter.java similarity index 95% rename from lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java rename to lib/src/main/java/net/tomatentum/marinara/wrapper/CommandConverter.java index e2f78f2..5cfc76c 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/CommandConverter.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandConverter.java @@ -1,9 +1,10 @@ -package net.tomatentum.marinara.interaction.commands; +package net.tomatentum.marinara.wrapper; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java index 6045b94..b5579b6 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JConverterSpec.java @@ -6,11 +6,11 @@ import discord4j.core.object.command.ApplicationCommandOption.Type; import discord4j.discordjson.json.ApplicationCommandOptionChoiceData; import discord4j.discordjson.json.ApplicationCommandOptionData; import discord4j.discordjson.json.ApplicationCommandRequest; -import net.tomatentum.marinara.interaction.commands.CommandConverter; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; +import net.tomatentum.marinara.wrapper.CommandConverter; public class Discord4JConverterSpec implements CommandConverter.Spec { diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java index 85a1e28..6b58a0b 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -19,10 +19,10 @@ import discord4j.discordjson.json.ApplicationCommandOptionData; import discord4j.discordjson.json.ApplicationCommandRequest; import net.tomatentum.marinara.interaction.InteractionType; -import net.tomatentum.marinara.interaction.commands.CommandConverter; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.util.LoggerUtil; +import net.tomatentum.marinara.wrapper.CommandConverter; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.wrapper.LibraryWrapper; diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java index e2748a1..e6bde68 100644 --- a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordConverterSpec.java @@ -10,9 +10,9 @@ import org.javacord.api.interaction.SlashCommandOptionChoice; import org.javacord.api.interaction.SlashCommandOptionChoiceBuilder; import org.javacord.api.interaction.SlashCommandOptionType; -import net.tomatentum.marinara.interaction.commands.CommandConverter; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; +import net.tomatentum.marinara.wrapper.CommandConverter; public class JavacordConverterSpec implements CommandConverter.Spec { 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 57e9c64..fb1a038 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 @@ -16,9 +16,9 @@ import org.javacord.api.interaction.SlashCommandOption; import org.javacord.api.interaction.SlashCommandOptionChoice; import net.tomatentum.marinara.interaction.InteractionType; -import net.tomatentum.marinara.interaction.commands.CommandConverter; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.CommandConverter; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.LibraryWrapper; -- 2.47.2 From 432cf78a2e19cf555f76d4a4b171a2b096d004d3 Mon Sep 17 00:00:00 2001 From: tueem Date: Wed, 5 Mar 2025 21:44:12 +0100 Subject: [PATCH 10/22] add IdentifierProvider and wrapper implementations --- .../ident/RootCommandIdentifier.java | 25 +++---- .../ident/SlashCommandIdentifier.java | 25 +++---- .../marinara/parser/SlashCommandParser.java | 6 +- .../registry/InteractionRegistry.java | 7 +- .../marinara/wrapper/IdentifierProvider.java | 72 +++++++++++++++++++ .../marinara/wrapper/LibraryWrapper.java | 7 +- .../wrapper/discord4j/Discord4JWrapper.java | 58 +++------------ .../AutocompleteIdentifierConverter.java | 38 ++++++++++ .../ButtonIdentifierConverter.java | 15 ++++ .../SlashCommandIdentifierConverter.java | 39 ++++++++++ .../wrapper/javacord/JavacordWrapper.java | 58 +++------------ .../AutocompleteIdentifierConverter.java | 37 ++++++++++ .../ButtonIdentifierConverter.java | 16 +++++ .../SlashCommandIdentifierConverter.java | 38 ++++++++++ 14 files changed, 305 insertions(+), 136 deletions(-) create mode 100644 lib/src/main/java/net/tomatentum/marinara/wrapper/IdentifierProvider.java create mode 100644 wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/AutocompleteIdentifierConverter.java create mode 100644 wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/ButtonIdentifierConverter.java create mode 100644 wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/SlashCommandIdentifierConverter.java create mode 100644 wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/AutocompleteIdentifierConverter.java create mode 100644 wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/ButtonIdentifierConverter.java create mode 100644 wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/SlashCommandIdentifierConverter.java diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java index d32a6a7..ae0e6d4 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/RootCommandIdentifier.java @@ -1,5 +1,6 @@ package net.tomatentum.marinara.interaction.ident; +import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption; public class RootCommandIdentifier extends SlashCommandIdentifier { @@ -10,10 +11,10 @@ public class RootCommandIdentifier extends SlashCommandIdentifier { InteractionIdentifier parent, String name, String description, + InteractionType type, SlashCommandOption[] options, - boolean isAutocomplete, long[] serverIds) { - super(parent, name, description, options, isAutocomplete); + super(parent, name, description, type, options); this.serverIds = serverIds; } @@ -26,7 +27,6 @@ public class RootCommandIdentifier extends SlashCommandIdentifier { private String name; private String description; private SlashCommandOption[] options; - private boolean isAutocomplete = false; private long[] serverIds; @@ -66,15 +66,6 @@ public class RootCommandIdentifier extends SlashCommandIdentifier { return this; } - public boolean autocomplete() { - return this.isAutocomplete; - } - - public Builder autocomplete(boolean isAutocomplete) { - this.isAutocomplete = isAutocomplete; - return this; - } - public long[] serverIds() { return this.serverIds; } @@ -84,8 +75,14 @@ public class RootCommandIdentifier extends SlashCommandIdentifier { return this; } - public SlashCommandIdentifier build() { - return new RootCommandIdentifier(parent, name, description, options, isAutocomplete, serverIds); + public SlashCommandIdentifier build(boolean autocomplete) { + return new RootCommandIdentifier( + parent, + name, + description, + autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND, + options, + serverIds); } } diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java index 8ecad75..7284a2a 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/SlashCommandIdentifier.java @@ -11,10 +11,10 @@ public class SlashCommandIdentifier extends InteractionIdentifier { InteractionIdentifier parent, String name, String description, - SlashCommandOption[] options, - boolean isAutocomplete + InteractionType type, + SlashCommandOption[] options ) { - super(parent, name, description, isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND); + super(parent, name, description, type); this.options = options; } @@ -27,7 +27,6 @@ public class SlashCommandIdentifier extends InteractionIdentifier { private String name; private String description; private SlashCommandOption[] options; - private boolean isAutocomplete = false; public InteractionIdentifier parent() { return parent; @@ -65,17 +64,13 @@ public class SlashCommandIdentifier extends InteractionIdentifier { return this; } - public boolean autocomplete() { - return this.isAutocomplete; - } - - public Builder autocomplete(boolean isAutocomplete) { - this.isAutocomplete = isAutocomplete; - return this; - } - - public SlashCommandIdentifier build() { - return new SlashCommandIdentifier(parent, name, description, options, isAutocomplete); + public SlashCommandIdentifier build(boolean autocomplete) { + return new SlashCommandIdentifier( + parent, + name, + description, + autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND, + options); } } diff --git a/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java b/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java index 0cd7072..ca07241 100644 --- a/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java +++ b/lib/src/main/java/net/tomatentum/marinara/parser/SlashCommandParser.java @@ -37,9 +37,8 @@ public class SlashCommandParser implements AnnotationParser { .name(cmd.name()) .description(cmd.description()) .options(cmd.options()) - .autocomplete(isAutoComplete) .serverIds(cmd.serverIds()) - .build(); + .build(isAutoComplete); if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) { SubCommandGroup cmdGroup = ReflectionUtil.getAnnotation(method, SubCommandGroup.class); @@ -57,8 +56,7 @@ public class SlashCommandParser implements AnnotationParser { .name(subCmd.name()) .description(subCmd.description()) .options(subCmd.options()) - .autocomplete(isAutoComplete) - .build(); + .build(isAutoComplete); } logger.trace("Parsed using SlashCommandParser for method {} with the result:\n{}", ReflectionUtil.getFullMethodName(method), lastIdentifier.toString()); 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 59d01b7..08677c9 100644 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java +++ b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java @@ -16,17 +16,19 @@ import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.util.LoggerUtil; -import net.tomatentum.marinara.wrapper.LibraryWrapper; +import net.tomatentum.marinara.wrapper.IdentifierProvider; import net.tomatentum.marinara.interaction.methods.InteractionMethod; public class InteractionRegistry { private Logger logger = LoggerUtil.getLogger(getClass()); private Set interactions; private Marinara marinara; + private IdentifierProvider identifierProvider; public InteractionRegistry(Marinara marinara) { this.interactions = new HashSet<>(); this.marinara = marinara; + this.identifierProvider = marinara.getWrapper().createIdentifierProvider(); marinara.getWrapper().subscribeInteractions(this::handle); } @@ -74,9 +76,8 @@ public class InteractionRegistry { public void handle(Object context) { logger.debug("Received {} interaction ", context); - LibraryWrapper wrapper = marinara.getWrapper(); interactions.forEach((e) -> { - if (wrapper.getInteractionIdentifier(context).equals(e.identifier())) { + if (this.identifierProvider.provide(context).equals(e.identifier())) { logger.info("Running {} interaction using {}\ncontext: {}", e.type(), e.toString(), context.toString()); e.runAll(context); } diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/IdentifierProvider.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/IdentifierProvider.java new file mode 100644 index 0000000..1d3f31d --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/IdentifierProvider.java @@ -0,0 +1,72 @@ +package net.tomatentum.marinara.wrapper; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.logging.log4j.Logger; + +import io.leangen.geantyref.GenericTypeReflector; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.util.LoggerUtil; +import net.tomatentum.marinara.util.ReflectionUtil; + +public class IdentifierProvider { + + public static IdentifierProvider of(Converter... converter) { + return new IdentifierProvider(Arrays.asList(converter)); + } + + private Map, Converter> converter; + private Logger logger = LoggerUtil.getLogger(getClass()); + + private IdentifierProvider(List> converter) { + this.converter = new HashMap<>(); + for (Converter conv : converter) { + if (conv.getClass().getName().contains("$$Lambda")) + throw new IllegalArgumentException("Lambdas cannot be used for IdentifierConverter because of Type erasure."); + Type type = GenericTypeReflector.getExactSuperType(conv.getClass(), Converter.class); + Type parameterType = (Class) ((ParameterizedType) type).getActualTypeArguments()[0]; + if (!(parameterType instanceof Class)) + throw new IllegalArgumentException("Only full Class types are supported by IdentiferConverters"); + this.converter.put((Class) parameterType, conv); + } + } + + public InteractionIdentifier provide(Object context) { + Type type = ReflectionUtil.getMostSpecificClass( + converter.keySet().stream().filter(x -> x.isAssignableFrom(context.getClass())).toArray(Class[]::new), + context.getClass()); + + if (type == null) + logger.debug("No Identifier converter found for context {}", context.getClass().toString()); + + @SuppressWarnings("unchecked") + Converter conv = (Converter) converter.get(type); + + return conv.convert(context); + } + + @FunctionalInterface + public interface Converter { + InteractionIdentifier convert(T context); + } + + public static class LambdaWrapper implements Converter { + + private Converter converter; + + LambdaWrapper(Converter converter) { + this.converter = converter; + } + + @Override + public InteractionIdentifier convert(T context) { + return this.converter.convert(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 0a4ede7..eeec879 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java @@ -5,14 +5,13 @@ import java.util.List; import java.util.function.Consumer; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; public abstract class LibraryWrapper { private List> interactionSubscriber; protected LibraryWrapper() { - interactionSubscriber = new ArrayList<>(); + this.interactionSubscriber = new ArrayList<>(); } public void handleInteraction(Object context) { @@ -27,8 +26,8 @@ public abstract class LibraryWrapper { } public abstract void registerSlashCommands(SlashCommandDefinition[] defs); - public abstract InteractionIdentifier getInteractionIdentifier(Object context); - + + public abstract IdentifierProvider createIdentifierProvider(); public abstract ContextObjectProvider getContextObjectProvider(); } \ No newline at end of file diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java index 6b58a0b..4490885 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -8,9 +8,6 @@ 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; @@ -18,13 +15,15 @@ import discord4j.discordjson.json.ApplicationCommandOptionChoiceData; import discord4j.discordjson.json.ApplicationCommandOptionData; import discord4j.discordjson.json.ApplicationCommandRequest; -import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.CommandConverter; import net.tomatentum.marinara.wrapper.ContextObjectProvider; +import net.tomatentum.marinara.wrapper.IdentifierProvider; import net.tomatentum.marinara.wrapper.LibraryWrapper; +import net.tomatentum.marinara.wrapper.discord4j.identifierconverter.AutocompleteIdentifierConverter; +import net.tomatentum.marinara.wrapper.discord4j.identifierconverter.ButtonIdentifierConverter; +import net.tomatentum.marinara.wrapper.discord4j.identifierconverter.SlashCommandIdentifierConverter; public class Discord4JWrapper extends LibraryWrapper { @@ -82,49 +81,12 @@ public class Discord4JWrapper extends LibraryWrapper { } @Override - public InteractionIdentifier getInteractionIdentifier(Object context) { - - if (context instanceof ButtonInteractionEvent) { - ButtonInteractionEvent interaction = (ButtonInteractionEvent) context; - return InteractionIdentifier.builder().name(interaction.getCustomId()).type(InteractionType.BUTTON).build(); - } - - List options; - String commandName; - boolean isAutocomplete = false; - - 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(); - isAutocomplete = true; - }else - return null; - - InteractionIdentifier last = InteractionIdentifier.slashBuilder().name(commandName).autocomplete(isAutocomplete).build(); - - if (!options.isEmpty()) { - List sub_options = SUB_FILTER.apply(options.getFirst().getOptions()); - if (!sub_options.isEmpty()) { - last = InteractionIdentifier.builder() - .name(options.getFirst().getName()) - .type(isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND) - .parent(last).build(); - last = InteractionIdentifier.slashBuilder() - .name(sub_options.getFirst().getName()) - .autocomplete(isAutocomplete) - .parent(last).build(); - }else - last = InteractionIdentifier.slashBuilder() - .name(options.getFirst().getName()) - .autocomplete(isAutocomplete) - .parent(last).build(); - } - return last; + public IdentifierProvider createIdentifierProvider() { + return IdentifierProvider.of( + new SlashCommandIdentifierConverter(), + new AutocompleteIdentifierConverter(), + new ButtonIdentifierConverter() + ); } @Override diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/AutocompleteIdentifierConverter.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/AutocompleteIdentifierConverter.java new file mode 100644 index 0000000..49761d9 --- /dev/null +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/AutocompleteIdentifierConverter.java @@ -0,0 +1,38 @@ +package net.tomatentum.marinara.wrapper.discord4j.identifierconverter; + +import java.util.List; + +import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent; +import discord4j.core.object.command.ApplicationCommandInteractionOption; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; +import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper; + +public class AutocompleteIdentifierConverter implements IdentifierProvider.Converter { + + @Override + public InteractionIdentifier convert(ChatInputAutoCompleteEvent context) { + List options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions()); + String commandName = context.getCommandName(); + + if (!options.isEmpty()) { + List sub_options = Discord4JWrapper.SUB_FILTER.apply(options.getFirst().getOptions()); + if (!sub_options.isEmpty()) + return InteractionIdentifier.createHierarchy( + InteractionType.AUTOCOMPLETE, + commandName, + options.getFirst().getName(), + sub_options.getFirst().getName()); + else + return InteractionIdentifier.createHierarchy( + InteractionType.AUTOCOMPLETE, + commandName, + options.getFirst().getName()); + }else + return InteractionIdentifier.createHierarchy( + InteractionType.AUTOCOMPLETE, + commandName); + } + +} diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/ButtonIdentifierConverter.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/ButtonIdentifierConverter.java new file mode 100644 index 0000000..8751d4f --- /dev/null +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/ButtonIdentifierConverter.java @@ -0,0 +1,15 @@ +package net.tomatentum.marinara.wrapper.discord4j.identifierconverter; + +import discord4j.core.event.domain.interaction.ButtonInteractionEvent; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; + +public class ButtonIdentifierConverter implements IdentifierProvider.Converter { + + @Override + public InteractionIdentifier convert(ButtonInteractionEvent context) { + return InteractionIdentifier.builder().name(context.getCustomId()).type(InteractionType.BUTTON).build(); + } + +} diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/SlashCommandIdentifierConverter.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/SlashCommandIdentifierConverter.java new file mode 100644 index 0000000..612cd0a --- /dev/null +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/identifierconverter/SlashCommandIdentifierConverter.java @@ -0,0 +1,39 @@ +package net.tomatentum.marinara.wrapper.discord4j.identifierconverter; + +import java.util.List; + +import discord4j.core.event.domain.interaction.ChatInputInteractionEvent; +import discord4j.core.object.command.ApplicationCommandInteractionOption; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; +import net.tomatentum.marinara.wrapper.discord4j.Discord4JWrapper; + +public class SlashCommandIdentifierConverter implements IdentifierProvider.Converter { + + @Override + public InteractionIdentifier convert(ChatInputInteractionEvent context) { + List options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions()); + String commandName = context.getCommandName(); + + if (!options.isEmpty()) { + List sub_options = Discord4JWrapper.SUB_FILTER.apply(options.getFirst().getOptions()); + if (!sub_options.isEmpty()) + return InteractionIdentifier.createHierarchy( + InteractionType.COMMAND, + commandName, + options.getFirst().getName(), + sub_options.getFirst().getName()); + else + return InteractionIdentifier.createHierarchy( + InteractionType.COMMAND, + commandName, + options.getFirst().getName()); + }else + return InteractionIdentifier.createHierarchy( + InteractionType.COMMAND, + commandName); + + } + +} 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 fb1a038..5545e32 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 @@ -2,26 +2,23 @@ package net.tomatentum.marinara.wrapper.javacord; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.apache.logging.log4j.Logger; import org.javacord.api.DiscordApi; -import org.javacord.api.interaction.AutocompleteInteraction; -import org.javacord.api.interaction.ButtonInteraction; import org.javacord.api.interaction.SlashCommandBuilder; -import org.javacord.api.interaction.SlashCommandInteraction; -import org.javacord.api.interaction.SlashCommandInteractionOption; import org.javacord.api.interaction.SlashCommandOption; import org.javacord.api.interaction.SlashCommandOptionChoice; -import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; -import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.wrapper.CommandConverter; import net.tomatentum.marinara.wrapper.ContextObjectProvider; +import net.tomatentum.marinara.wrapper.IdentifierProvider; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.LibraryWrapper; +import net.tomatentum.marinara.wrapper.javacord.identifierconverter.AutocompleteIdentifierConverter; +import net.tomatentum.marinara.wrapper.javacord.identifierconverter.ButtonIdentifierConverter; +import net.tomatentum.marinara.wrapper.javacord.identifierconverter.SlashCommandIdentifierConverter; public class JavacordWrapper extends LibraryWrapper { @@ -65,47 +62,12 @@ public class JavacordWrapper extends LibraryWrapper { } @Override - public InteractionIdentifier getInteractionIdentifier(Object context) { - if (context instanceof ButtonInteraction) { - ButtonInteraction button = (ButtonInteraction) context; - return InteractionIdentifier.builder().name(button.getCustomId()).type(InteractionType.BUTTON).build(); - } - - if (!(context instanceof SlashCommandInteraction)) - return null; - - boolean isAutocomplete = false; - - if (context instanceof AutocompleteInteraction) - isAutocomplete = true; - - SlashCommandInteraction interaction = (SlashCommandInteraction) context; - InteractionIdentifier lastIdentifier = InteractionIdentifier.rootBuilder() - .name(interaction.getCommandName()) - .autocomplete(isAutocomplete) - .build(); - List options = interaction.getOptions(); - if (!options.isEmpty()) { - if (!options.getFirst().getArguments().isEmpty()) { - lastIdentifier = InteractionIdentifier.builder() - .name(options.getFirst().getName()) - .type(isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND) - .parent(lastIdentifier) - .build(); - lastIdentifier = InteractionIdentifier.slashBuilder() - .name(options.getFirst().getOptions().getFirst().getName()) - .autocomplete(isAutocomplete) - .parent(lastIdentifier) - .build(); - }else - lastIdentifier = InteractionIdentifier.slashBuilder() - .name(options.getFirst().getName()) - .autocomplete(isAutocomplete) - .parent(lastIdentifier) - .build(); - } - - return lastIdentifier; + public IdentifierProvider createIdentifierProvider() { + return IdentifierProvider.of( + new SlashCommandIdentifierConverter(), + new AutocompleteIdentifierConverter(), + new ButtonIdentifierConverter() + ); } @Override diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/AutocompleteIdentifierConverter.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/AutocompleteIdentifierConverter.java new file mode 100644 index 0000000..65fef44 --- /dev/null +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/AutocompleteIdentifierConverter.java @@ -0,0 +1,37 @@ +package net.tomatentum.marinara.wrapper.javacord.identifierconverter; + +import java.util.List; + +import org.javacord.api.interaction.AutocompleteInteraction; +import org.javacord.api.interaction.SlashCommandInteractionOption; + +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; + +public class AutocompleteIdentifierConverter implements IdentifierProvider.Converter { + + @Override + public InteractionIdentifier convert(AutocompleteInteraction context) { + List options = context.getOptions(); + String commandName = context.getCommandName(); + if (!options.isEmpty()) { + List sub_options = context.getOptions().getFirst().getOptions(); + if (!sub_options.isEmpty()) + return InteractionIdentifier.createHierarchy( + InteractionType.AUTOCOMPLETE, + commandName, + options.getFirst().getName(), + sub_options.getFirst().getName()); + else + return InteractionIdentifier.createHierarchy( + InteractionType.AUTOCOMPLETE, + commandName, + options.getFirst().getName()); + }else + return InteractionIdentifier.createHierarchy( + InteractionType.AUTOCOMPLETE, + commandName); + } + +} diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/ButtonIdentifierConverter.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/ButtonIdentifierConverter.java new file mode 100644 index 0000000..209ce32 --- /dev/null +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/ButtonIdentifierConverter.java @@ -0,0 +1,16 @@ +package net.tomatentum.marinara.wrapper.javacord.identifierconverter; + +import org.javacord.api.interaction.ButtonInteraction; + +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; + +public class ButtonIdentifierConverter implements IdentifierProvider.Converter { + + @Override + public InteractionIdentifier convert(ButtonInteraction context) { + return InteractionIdentifier.builder().name(context.getCustomId()).type(InteractionType.BUTTON).build(); + } + +} diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/SlashCommandIdentifierConverter.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/SlashCommandIdentifierConverter.java new file mode 100644 index 0000000..4b90bd1 --- /dev/null +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/identifierconverter/SlashCommandIdentifierConverter.java @@ -0,0 +1,38 @@ +package net.tomatentum.marinara.wrapper.javacord.identifierconverter; + +import java.util.List; + +import org.javacord.api.interaction.SlashCommandInteraction; +import org.javacord.api.interaction.SlashCommandInteractionOption; + +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.wrapper.IdentifierProvider; + +public class SlashCommandIdentifierConverter implements IdentifierProvider.Converter { + + @Override + public InteractionIdentifier convert(SlashCommandInteraction context) { + List options = context.getOptions(); + String commandName = context.getCommandName(); + if (!options.isEmpty()) { + List sub_options = context.getOptions().getFirst().getOptions(); + if (!sub_options.isEmpty()) + return InteractionIdentifier.createHierarchy( + InteractionType.COMMAND, + commandName, + options.getFirst().getName(), + sub_options.getFirst().getName()); + else + return InteractionIdentifier.createHierarchy( + InteractionType.COMMAND, + commandName, + options.getFirst().getName()); + }else + return InteractionIdentifier.createHierarchy( + InteractionType.COMMAND, + commandName); + + } + +} -- 2.47.2 From 4e27e6ce5659717ec1ac1e9e23801cc1819177df Mon Sep 17 00:00:00 2001 From: tueem Date: Sun, 16 Mar 2025 01:36:23 +0100 Subject: [PATCH 11/22] feat(struct): introduce ObjectAggregator --- .../registry/InteractionRegistry.java | 29 +++++++---------- .../marinara/util/ObjectAggregator.java | 31 +++++++++++++++++++ 2 files changed, 42 insertions(+), 18 deletions(-) create mode 100644 lib/src/main/java/net/tomatentum/marinara/util/ObjectAggregator.java 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 08677c9..bf54dad 100644 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java +++ b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java @@ -1,7 +1,6 @@ package net.tomatentum.marinara.registry; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; @@ -13,9 +12,10 @@ import net.tomatentum.marinara.Marinara; import net.tomatentum.marinara.interaction.InteractionHandler; import net.tomatentum.marinara.interaction.InteractionType; import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier; -import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier; import net.tomatentum.marinara.util.LoggerUtil; +import net.tomatentum.marinara.util.ObjectAggregator; import net.tomatentum.marinara.wrapper.IdentifierProvider; import net.tomatentum.marinara.interaction.methods.InteractionMethod; @@ -51,26 +51,19 @@ public class InteractionRegistry { } public void registerCommands() { - List defs = new ArrayList<>(); - List slashIdentifiers = interactions.stream() + List slashIdentifiers = interactions.stream() .filter((x) -> x.type().equals(InteractionType.COMMAND)) - .map((x) -> (SlashCommandIdentifier)x.identifier()) + .map((x) -> x.identifier()) .toList(); - slashIdentifiers.forEach((ident) -> { - Optional appDef = defs.stream() - .filter((x) -> x.rootIdentifier().equals(ident.rootNode())) - .findFirst(); + SlashCommandDefinition[] defs = new ObjectAggregator( + i -> (RootCommandIdentifier)i.rootNode(), + SlashCommandDefinition::addIdentifier, + SlashCommandDefinition::new) + .aggregate(slashIdentifiers) + .toArray(SlashCommandDefinition[]::new); - if (appDef.isPresent()) - appDef.get().addIdentifier(ident); - else - defs.add( - new SlashCommandDefinition((RootCommandIdentifier) ident.rootNode()) - .addIdentifier(ident)); - }); - - marinara.getWrapper().registerSlashCommands(defs.toArray(SlashCommandDefinition[]::new)); + marinara.getWrapper().registerSlashCommands(defs); logger.info("Registered all SlashCommands"); } diff --git a/lib/src/main/java/net/tomatentum/marinara/util/ObjectAggregator.java b/lib/src/main/java/net/tomatentum/marinara/util/ObjectAggregator.java new file mode 100644 index 0000000..e16b88a --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/util/ObjectAggregator.java @@ -0,0 +1,31 @@ +package net.tomatentum.marinara.util; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; + +public class ObjectAggregator { + private Function keySupplier; + private BiConsumer valueConsumer; + private Function defaultGenerator; + + public ObjectAggregator(Function keySupplier, BiConsumer valueConsumer, Function defaultGenerator) { + this.keySupplier = keySupplier; + this.valueConsumer = valueConsumer; + this.defaultGenerator = defaultGenerator; + } + + public Collection aggregate(Iterable iterator) { + Map map = new HashMap<>(); + for (O element : iterator) { + K key = this.keySupplier.apply(element); + V value = map.getOrDefault(key, this.defaultGenerator.apply(key)); + this.valueConsumer.accept(value, element); + map.putIfAbsent(key, value); + } + return map.values(); + } + +} -- 2.47.2 From 630c8ddee5a3756115075d086c43123c7013493b Mon Sep 17 00:00:00 2001 From: tueem Date: Sun, 16 Mar 2025 01:49:24 +0100 Subject: [PATCH 12/22] feat(register): add convenience getter --- .../marinara/interaction/commands/SlashCommandDefinition.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java index a1525c9..a6be589 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java @@ -95,6 +95,10 @@ public class SlashCommandDefinition { return this.rootIdentifier().equals(other.rootIdentifier()); } + public long[] serverIds() { + return rootIdentifier().serverIds(); + } + public Set entries() { return this.entries; } -- 2.47.2 From 7287d44645487a437edb44878698ab6c29051944 Mon Sep 17 00:00:00 2001 From: tueem Date: Sun, 16 Mar 2025 02:46:55 +0100 Subject: [PATCH 13/22] refactor(util): add multiple key support to ObjectAggregator --- .../registry/InteractionRegistry.java | 3 ++- .../marinara/util/ObjectAggregator.java | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) 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 bf54dad..3c3dc9c 100644 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java +++ b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java @@ -1,6 +1,7 @@ package net.tomatentum.marinara.registry; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Optional; @@ -57,7 +58,7 @@ public class InteractionRegistry { .toList(); SlashCommandDefinition[] defs = new ObjectAggregator( - i -> (RootCommandIdentifier)i.rootNode(), + i -> Arrays.asList((RootCommandIdentifier)i.rootNode()), SlashCommandDefinition::addIdentifier, SlashCommandDefinition::new) .aggregate(slashIdentifiers) diff --git a/lib/src/main/java/net/tomatentum/marinara/util/ObjectAggregator.java b/lib/src/main/java/net/tomatentum/marinara/util/ObjectAggregator.java index e16b88a..b02488f 100644 --- a/lib/src/main/java/net/tomatentum/marinara/util/ObjectAggregator.java +++ b/lib/src/main/java/net/tomatentum/marinara/util/ObjectAggregator.java @@ -5,25 +5,40 @@ import java.util.HashMap; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.function.Supplier; public class ObjectAggregator { - private Function keySupplier; + private Function> keySupplier; private BiConsumer valueConsumer; private Function defaultGenerator; - public ObjectAggregator(Function keySupplier, BiConsumer valueConsumer, Function defaultGenerator) { + public ObjectAggregator( + Function> keySupplier, + BiConsumer valueConsumer, + Function defaultGenerator) { this.keySupplier = keySupplier; this.valueConsumer = valueConsumer; this.defaultGenerator = defaultGenerator; } + public ObjectAggregator( + Function> keySupplier, + BiConsumer valueConsumer, + Supplier defaultGenerator) { + this.keySupplier = keySupplier; + this.valueConsumer = valueConsumer; + this.defaultGenerator = _ -> defaultGenerator.get(); + } + public Collection aggregate(Iterable iterator) { Map map = new HashMap<>(); for (O element : iterator) { - K key = this.keySupplier.apply(element); - V value = map.getOrDefault(key, this.defaultGenerator.apply(key)); - this.valueConsumer.accept(value, element); - map.putIfAbsent(key, value); + Iterable keys = this.keySupplier.apply(element); + for (K key : keys) { + V value = map.getOrDefault(key, this.defaultGenerator.apply(key)); + this.valueConsumer.accept(value, element); + map.putIfAbsent(key, value); + } } return map.values(); } -- 2.47.2 From 78cacb7eb6ecb271ae4bda04fb6be7b4dc6eeb8b Mon Sep 17 00:00:00 2001 From: tueem Date: Sun, 16 Mar 2025 02:47:16 +0100 Subject: [PATCH 14/22] feat(util): add ObjectListAggregator --- .../marinara/util/ObjectListAggregator.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/src/main/java/net/tomatentum/marinara/util/ObjectListAggregator.java diff --git a/lib/src/main/java/net/tomatentum/marinara/util/ObjectListAggregator.java b/lib/src/main/java/net/tomatentum/marinara/util/ObjectListAggregator.java new file mode 100644 index 0000000..9494467 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/util/ObjectListAggregator.java @@ -0,0 +1,15 @@ +package net.tomatentum.marinara.util; + +import java.util.ArrayList; +import java.util.function.Function; + +public class ObjectListAggregator extends ObjectAggregator> { + + public ObjectListAggregator(Function keySupplier, Function valueConsumer) { + super(keySupplier, + (l, o) -> l.add(valueConsumer.apply(o)), + () -> new ArrayList<>()); + } + + +} -- 2.47.2 From e3fc10a1ce17e34c53b1feb25a6a8ae10fca2e1e Mon Sep 17 00:00:00 2001 From: tueem Date: Sun, 16 Mar 2025 02:48:24 +0100 Subject: [PATCH 15/22] fix(util): ObjectListAggregator syntax --- .../java/net/tomatentum/marinara/util/ObjectListAggregator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/net/tomatentum/marinara/util/ObjectListAggregator.java b/lib/src/main/java/net/tomatentum/marinara/util/ObjectListAggregator.java index 9494467..c3ec89a 100644 --- a/lib/src/main/java/net/tomatentum/marinara/util/ObjectListAggregator.java +++ b/lib/src/main/java/net/tomatentum/marinara/util/ObjectListAggregator.java @@ -5,7 +5,7 @@ import java.util.function.Function; public class ObjectListAggregator extends ObjectAggregator> { - public ObjectListAggregator(Function keySupplier, Function valueConsumer) { + public ObjectListAggregator(Function> keySupplier, Function valueConsumer) { super(keySupplier, (l, o) -> l.add(valueConsumer.apply(o)), () -> new ArrayList<>()); -- 2.47.2 From 24df1731daac8b9d0180ccd0a534856a88d2bd24 Mon Sep 17 00:00:00 2001 From: tueem Date: Sun, 16 Mar 2025 17:06:37 +0100 Subject: [PATCH 16/22] refactor(command): add CommandRegisterer --- .../registry/InteractionRegistry.java | 2 +- .../marinara/wrapper/CommandRegisterer.java | 45 +++++++++++++++++++ .../marinara/wrapper/LibraryWrapper.java | 6 +-- .../marinara/wrapper/ServerCommandList.java | 16 +++++++ 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 lib/src/main/java/net/tomatentum/marinara/wrapper/CommandRegisterer.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/wrapper/ServerCommandList.java 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 3c3dc9c..a708c71 100644 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java +++ b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java @@ -64,7 +64,7 @@ public class InteractionRegistry { .aggregate(slashIdentifiers) .toArray(SlashCommandDefinition[]::new); - marinara.getWrapper().registerSlashCommands(defs); + marinara.getWrapper().getRegisterer().register(defs); logger.info("Registered all SlashCommands"); } diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandRegisterer.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandRegisterer.java new file mode 100644 index 0000000..41e17b0 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/CommandRegisterer.java @@ -0,0 +1,45 @@ +package net.tomatentum.marinara.wrapper; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; +import net.tomatentum.marinara.util.ObjectAggregator; + +public class CommandRegisterer { + + public static CommandRegisterer of(Strategy strategy, CommandConverter converter) { + return new CommandRegisterer(strategy, converter); + } + + private Strategy strategy; + private CommandConverter converter; + + CommandRegisterer(Strategy strategy, CommandConverter converter) { + this.strategy = strategy; + this.converter = converter; + } + + public void register(SlashCommandDefinition[] slashDefs) { + Set> serverCommands = new ObjectAggregator>( + def -> Arrays.stream(def.serverIds()).boxed().toList(), + (l, o) -> l.add(converter.convert(o)), + ServerCommandList::new) + .aggregate(Arrays.asList(slashDefs)).stream() + .collect(Collectors.toSet()); + + Set globalCommands = Arrays.stream(slashDefs) + .filter(x -> x.serverIds().length <= 0) + .map(converter::convert) + .collect(Collectors.toSet()); + + serverCommands.forEach(strategy::registerServer); + strategy.registerGlobal(globalCommands); + } + + public interface Strategy { + void registerServer(ServerCommandList commands); + void registerGlobal(Set defs); + } +} 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 eeec879..5b3ba04 100644 --- a/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/LibraryWrapper.java @@ -3,9 +3,6 @@ package net.tomatentum.marinara.wrapper; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; - -import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; - public abstract class LibraryWrapper { private List> interactionSubscriber; @@ -25,8 +22,7 @@ public abstract class LibraryWrapper { interactionSubscriber.remove(consumer); } - public abstract void registerSlashCommands(SlashCommandDefinition[] defs); - + public abstract CommandRegisterer getRegisterer(); public abstract IdentifierProvider createIdentifierProvider(); public abstract ContextObjectProvider getContextObjectProvider(); diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/ServerCommandList.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/ServerCommandList.java new file mode 100644 index 0000000..24fdf29 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/ServerCommandList.java @@ -0,0 +1,16 @@ +package net.tomatentum.marinara.wrapper; + +import java.util.HashSet; + +public class ServerCommandList extends HashSet{ + + private long serverId; + + public ServerCommandList(long serverId) { + this.serverId = serverId; + } + + public long serverId() { + return serverId; + } +} -- 2.47.2 From 203498de68e4618926e32c39dd4b8cb4bfe5d541 Mon Sep 17 00:00:00 2001 From: tueem Date: Sun, 16 Mar 2025 17:07:14 +0100 Subject: [PATCH 17/22] refactor(javacord): implement CommandRegisterer refactor --- .../javacord/JavacordRegistererStrategy.java | 29 +++++++++++++++ .../wrapper/javacord/JavacordWrapper.java | 35 ++++--------------- 2 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordRegistererStrategy.java diff --git a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordRegistererStrategy.java b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordRegistererStrategy.java new file mode 100644 index 0000000..4719f28 --- /dev/null +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordRegistererStrategy.java @@ -0,0 +1,29 @@ +package net.tomatentum.marinara.wrapper.javacord; + +import java.util.Set; + +import org.javacord.api.DiscordApi; +import org.javacord.api.interaction.SlashCommandBuilder; + +import net.tomatentum.marinara.wrapper.CommandRegisterer; +import net.tomatentum.marinara.wrapper.ServerCommandList; + +public class JavacordRegistererStrategy implements CommandRegisterer.Strategy { + + private DiscordApi api; + + public JavacordRegistererStrategy(DiscordApi api) { + this.api = api; + } + + @Override + public void registerServer(ServerCommandList commands) { + api.bulkOverwriteServerApplicationCommands(commands.serverId(), commands); + } + + @Override + public void registerGlobal(Set defs) { + api.bulkOverwriteGlobalApplicationCommands(defs); + } + +} 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 5545e32..d3680fa 100644 --- a/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java +++ b/wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord/JavacordWrapper.java @@ -1,17 +1,11 @@ package net.tomatentum.marinara.wrapper.javacord; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - import org.apache.logging.log4j.Logger; import org.javacord.api.DiscordApi; import org.javacord.api.interaction.SlashCommandBuilder; -import org.javacord.api.interaction.SlashCommandOption; -import org.javacord.api.interaction.SlashCommandOptionChoice; -import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.wrapper.CommandConverter; +import net.tomatentum.marinara.wrapper.CommandRegisterer; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.wrapper.IdentifierProvider; import net.tomatentum.marinara.util.LoggerUtil; @@ -22,16 +16,15 @@ import net.tomatentum.marinara.wrapper.javacord.identifierconverter.SlashCommand public class JavacordWrapper extends LibraryWrapper { - private DiscordApi api; private JavacordContextObjectProvider contextObjectProvider; - private CommandConverter commandConverter; + private CommandRegisterer commandRegisterer; private Logger logger = LoggerUtil.getLogger(getClass()); public JavacordWrapper(DiscordApi api) { - this.api = api; this.contextObjectProvider = new JavacordContextObjectProvider(); - this.commandConverter = CommandConverter.of(new JavacordConverterSpec()); + var converter = CommandConverter.of(new JavacordConverterSpec()); + this.commandRegisterer = CommandRegisterer.of(new JavacordRegistererStrategy(api), converter); if (api != null) api.addInteractionCreateListener((e) -> handleInteraction(e.getInteraction())); @@ -41,24 +34,8 @@ public class JavacordWrapper extends LibraryWrapper { } @Override - public void registerSlashCommands(SlashCommandDefinition[] defs) { - HashMap> serverCommands = new HashMap<>(); - Set globalCommands = new HashSet<>(); - for (SlashCommandDefinition slashCommandDefinition : defs) { - SlashCommandBuilder builder = commandConverter.convert(slashCommandDefinition); - if (slashCommandDefinition.rootIdentifier().serverIds().length > 0) { - for (long serverId : slashCommandDefinition.rootIdentifier().serverIds()) { - serverCommands.putIfAbsent(serverId, new HashSet<>()); - serverCommands.get(serverId).add(builder); - } - }else - globalCommands.add(builder); - } - - for (long serverId : serverCommands.keySet()) { - api.bulkOverwriteServerApplicationCommands(serverId, serverCommands.get(serverId)); - } - api.bulkOverwriteGlobalApplicationCommands(globalCommands); + public CommandRegisterer getRegisterer() { + return this.commandRegisterer; } @Override -- 2.47.2 From bae077654ed1bc7838f23fa25de02d8675970909 Mon Sep 17 00:00:00 2001 From: tueem Date: Sun, 16 Mar 2025 17:16:26 +0100 Subject: [PATCH 18/22] refactor(Discord4J): implement CommandRegisterer refactor --- .../Discord4JRegistererStrategy.java | 32 ++++++++++++++++ .../wrapper/discord4j/Discord4JWrapper.java | 37 ++++--------------- 2 files changed, 39 insertions(+), 30 deletions(-) create mode 100644 wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JRegistererStrategy.java diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JRegistererStrategy.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JRegistererStrategy.java new file mode 100644 index 0000000..fea6e5c --- /dev/null +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JRegistererStrategy.java @@ -0,0 +1,32 @@ +package net.tomatentum.marinara.wrapper.discord4j; + +import java.util.ArrayList; +import java.util.Set; + +import discord4j.core.GatewayDiscordClient; +import discord4j.discordjson.json.ApplicationCommandRequest; +import discord4j.rest.service.ApplicationService; +import net.tomatentum.marinara.wrapper.CommandRegisterer; +import net.tomatentum.marinara.wrapper.ServerCommandList; + +public class Discord4JRegistererStrategy implements CommandRegisterer.Strategy { + + private ApplicationService appService; + private long applicationId; + + public Discord4JRegistererStrategy(GatewayDiscordClient api) { + this.appService = api.getRestClient().getApplicationService(); + this.applicationId = api.getRestClient().getApplicationId().block(); + } + + @Override + public void registerServer(ServerCommandList commands) { + appService.bulkOverwriteGuildApplicationCommand(applicationId, commands.serverId(), new ArrayList<>(commands)); + + } + + @Override + public void registerGlobal(Set defs) { + appService.bulkOverwriteGlobalApplicationCommand(applicationId, new ArrayList<>(defs)); + } +} diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java index 4490885..5908683 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -1,7 +1,5 @@ package net.tomatentum.marinara.wrapper.discord4j; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.function.Function; @@ -11,13 +9,11 @@ import discord4j.core.GatewayDiscordClient; 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 net.tomatentum.marinara.interaction.commands.SlashCommandDefinition; import net.tomatentum.marinara.util.LoggerUtil; import net.tomatentum.marinara.wrapper.CommandConverter; +import net.tomatentum.marinara.wrapper.CommandRegisterer; import net.tomatentum.marinara.wrapper.ContextObjectProvider; import net.tomatentum.marinara.wrapper.IdentifierProvider; import net.tomatentum.marinara.wrapper.LibraryWrapper; @@ -37,16 +33,15 @@ public class Discord4JWrapper extends LibraryWrapper { .filter(o -> !o.getType().equals(Type.SUB_COMMAND) && !o.getType().equals(Type.SUB_COMMAND_GROUP)) .toList(); - private GatewayDiscordClient api; private Discord4JContextObjectProvider contextObjectProvider; - private CommandConverter commandConverter; + private CommandRegisterer commandRegisterer; private Logger logger = LoggerUtil.getLogger(getClass()); public Discord4JWrapper(GatewayDiscordClient api) { - this.api = api; this.contextObjectProvider = new Discord4JContextObjectProvider(); - this.commandConverter = CommandConverter.of(new Discord4JConverterSpec()); + var converter = CommandConverter.of(new Discord4JConverterSpec()); + this.commandRegisterer = CommandRegisterer.of(new Discord4JRegistererStrategy(api), converter); if (api != null) api.on(InteractionCreateEvent.class) @@ -58,26 +53,8 @@ public class Discord4JWrapper extends LibraryWrapper { } @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 = this.commandConverter.convert(slashCommandDefinition); - if (slashCommandDefinition.rootIdentifier().serverIds().length > 0) { - for (long serverId : slashCommandDefinition.rootIdentifier().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); + public CommandRegisterer getRegisterer() { + return this.commandRegisterer; } @Override @@ -93,5 +70,5 @@ public class Discord4JWrapper extends LibraryWrapper { public ContextObjectProvider getContextObjectProvider() { return this.contextObjectProvider; } - + } -- 2.47.2 From bce4ce781204109ec7ff85eb12cdc026c0a740b3 Mon Sep 17 00:00:00 2001 From: Tueem Date: Sun, 16 Mar 2025 23:35:39 +0100 Subject: [PATCH 19/22] fix(wrapper): add condition for CommandRegisterer if api is null --- .../marinara/wrapper/discord4j/Discord4JWrapper.java | 6 +++--- .../marinara/wrapper/javacord/JavacordWrapper.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java index 5908683..b14ce0f 100644 --- a/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java +++ b/wrapper/discord4j/src/main/java/net/tomatentum/marinara/wrapper/discord4j/Discord4JWrapper.java @@ -41,12 +41,12 @@ public class Discord4JWrapper extends LibraryWrapper { public Discord4JWrapper(GatewayDiscordClient api) { this.contextObjectProvider = new Discord4JContextObjectProvider(); var converter = CommandConverter.of(new Discord4JConverterSpec()); - this.commandRegisterer = CommandRegisterer.of(new Discord4JRegistererStrategy(api), converter); - if (api != null) + if (api != null) { + this.commandRegisterer = CommandRegisterer.of(new Discord4JRegistererStrategy(api), converter); api.on(InteractionCreateEvent.class) .subscribe(event -> handleInteraction(event)); - else + }else logger.warn("GatewayDiscordClient was null so no Events were subscribed to."); logger.info("Discord4J wrapper loaded!"); 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 d3680fa..0390fc0 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 @@ -24,11 +24,11 @@ public class JavacordWrapper extends LibraryWrapper { public JavacordWrapper(DiscordApi api) { this.contextObjectProvider = new JavacordContextObjectProvider(); var converter = CommandConverter.of(new JavacordConverterSpec()); - this.commandRegisterer = CommandRegisterer.of(new JavacordRegistererStrategy(api), converter); - if (api != null) + if (api != null) { + this.commandRegisterer = CommandRegisterer.of(new JavacordRegistererStrategy(api), converter); api.addInteractionCreateListener((e) -> handleInteraction(e.getInteraction())); - else + }else logger.warn("DiscordApi was null so no Events were subscribed to."); logger.info("Javacord wrapper loaded!"); } -- 2.47.2 From d4a91f3251e1de4ed67ba91f9cdf8b02a1ea774e Mon Sep 17 00:00:00 2001 From: Tueem Date: Mon, 17 Mar 2025 00:15:10 +0100 Subject: [PATCH 20/22] fix(core): fix wrong equality method and refactor a bit --- .../marinara/registry/InteractionRegistry.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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 a708c71..6314b88 100644 --- a/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java +++ b/lib/src/main/java/net/tomatentum/marinara/registry/InteractionRegistry.java @@ -40,11 +40,12 @@ public class InteractionRegistry { for (Method method : interactionHandler.getClass().getMethods()) { InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, marinara); if (iMethod != null) { - Optional entry = this.interactions.stream().filter(iMethod::equals).findFirst(); - if (entry.isEmpty()) { - interactions.add(new InteractionEntry(iMethod.identifier()).addMethod(iMethod)); - }else - entry.get().addMethod(iMethod); + Optional oentry = this.interactions.stream() + .filter(i -> i.identifier().equals(iMethod.identifier())) + .findFirst(); + + InteractionEntry entry = oentry.orElse(new InteractionEntry(iMethod.identifier())).addMethod(iMethod); + if (oentry.isEmpty()) this.interactions.add(entry); logger.debug("Added {} method from {}", iMethod.method().getName(), interactionHandler.getClass().getSimpleName()); } } -- 2.47.2 From e7c35d9308df60b6b6dd344b26e27cece3df0061 Mon Sep 17 00:00:00 2001 From: Tueem Date: Mon, 17 Mar 2025 00:16:26 +0100 Subject: [PATCH 21/22] refactor(core): remove redundant distinct method and its uses --- .../commands/SlashCommandDefinition.java | 6 +++--- .../ident/InteractionIdentifier.java | 17 ----------------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java index a6be589..164eec4 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/commands/SlashCommandDefinition.java @@ -66,13 +66,13 @@ public class SlashCommandDefinition { .map(x -> x.parent()) .toList(); - return InteractionIdentifier.distinct(subCommandGroups).toArray(SlashCommandIdentifier[]::new); + return subCommandGroups.toArray(SlashCommandIdentifier[]::new); } public SlashCommandIdentifier[] getSubCommands() { if (isRootCommand) return null; - return InteractionIdentifier.distinct(entries.stream().filter(x -> x.parent() instanceof RootCommandIdentifier).toList()).toArray(SlashCommandIdentifier[]::new); + return entries.stream().filter(x -> x.parent() instanceof RootCommandIdentifier).toArray(SlashCommandIdentifier[]::new); } public SlashCommandIdentifier[] getSubCommands(String groupName) { @@ -84,7 +84,7 @@ public class SlashCommandDefinition { .map(x -> x.parent().parent()) .toList(); - return InteractionIdentifier.distinct(subCommands).toArray(SlashCommandIdentifier[]::new); + return subCommands.toArray(SlashCommandIdentifier[]::new); } @Override diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java index 14a6bfd..7207738 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/ident/InteractionIdentifier.java @@ -1,8 +1,5 @@ package net.tomatentum.marinara.interaction.ident; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; import java.util.Objects; import net.tomatentum.marinara.interaction.InteractionType; @@ -37,20 +34,6 @@ public class InteractionIdentifier { receiver.description = provider.description(); tryAddDescriptions(receiver.parent(), provider.parent()); } - - /* - * TODO: Might not be the best solution. Propagating to future - * returns only one Identifier per name and takes the first present description - */ - public static Collection distinct(List identifiers) { - HashMap distinctIdentifiers = new HashMap<>(); - identifiers.forEach((x) -> { - InteractionIdentifier current = distinctIdentifiers.get(x.name()); - if (current == null || (current.description().isBlank() && !x.description().isBlank())) - distinctIdentifiers.put(x.name(), x); - }); - return distinctIdentifiers.values(); - } private InteractionIdentifier parent; private String name; -- 2.47.2 From d32ac62b4a715e27fa93a2981fa96d58689fdcfc Mon Sep 17 00:00:00 2001 From: tueem Date: Mon, 17 Mar 2025 08:37:11 +0100 Subject: [PATCH 22/22] fix(autocomplete): fix autocomplete using component context objects --- .../interaction/methods/AutoCompleteInteractionMethod.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java index fc08e4d..a5d53b4 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/methods/AutoCompleteInteractionMethod.java @@ -33,7 +33,7 @@ public class AutoCompleteInteractionMethod extends InteractionMethod { if (autocompleteOptionValue != null) return autocompleteOptionValue; - return marinara.getWrapper().getContextObjectProvider().getComponentContextObject(context, type); + return marinara.getWrapper().getContextObjectProvider().getInteractionContextObject(context, type); } @Override -- 2.47.2