Merge pull request 'improve wrapper and general structure' (#16) from improve/structure into dev
Reviewed-on: #16 No new features
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -6,3 +6,4 @@ build
 | 
				
			|||||||
.vscode
 | 
					.vscode
 | 
				
			||||||
lib/bin
 | 
					lib/bin
 | 
				
			||||||
wrapper/javacord/bin
 | 
					wrapper/javacord/bin
 | 
				
			||||||
 | 
					wrapper/discord4j/bin
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,94 +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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,99 +1,110 @@
 | 
				
			|||||||
package net.tomatentum.marinara.interaction.commands;
 | 
					package net.tomatentum.marinara.interaction.commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.Arrays;
 | 
					 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
 | 
					import org.apache.logging.log4j.Logger;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
 | 
					
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
 | 
					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 {
 | 
					public class SlashCommandDefinition {
 | 
				
			||||||
    private List<ExecutableSlashCommandDefinition> executableDefinitons;
 | 
					 | 
				
			||||||
    private SlashCommand slashCommand;
 | 
					 | 
				
			||||||
    private boolean isRootCommand;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SlashCommandDefinition(SlashCommand applicationCommand) {
 | 
					    public static SlashCommandOptionChoice[] getActualChoices(SlashCommandOption option) {
 | 
				
			||||||
        this.executableDefinitons = new ArrayList<>();
 | 
					        SlashCommandOptionChoice[] choices = option.choices();
 | 
				
			||||||
        this.slashCommand = applicationCommand;
 | 
					        if (choices.length <= 0 && !option.choiceEnum().equals(PlaceHolderEnum.class))
 | 
				
			||||||
 | 
					            choices = EnumChoices.of(option.choiceEnum()).choices();
 | 
				
			||||||
 | 
					        return choices;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SlashCommandDefinition addExecutableCommand(ExecutableSlashCommandDefinition def) {
 | 
					    private Set<InteractionIdentifier> entries;
 | 
				
			||||||
        if (def.applicationCommand() != null) {
 | 
					    private RootCommandIdentifier rootIdentifier;
 | 
				
			||||||
            if (slashCommand == null)
 | 
					    private boolean isRootCommand;
 | 
				
			||||||
                this.slashCommand = def.applicationCommand();
 | 
					
 | 
				
			||||||
            if (!this.slashCommand.name().equals(def.applicationCommand().name()))
 | 
					    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
				
			||||||
                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");
 | 
					
 | 
				
			||||||
 | 
					    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");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (executableDefinitons.isEmpty())
 | 
					        entries.add(identifier);
 | 
				
			||||||
            this.isRootCommand = def.isRootCommand();
 | 
					        this.logger.debug("Added identifer {} to command {}", identifier, rootIdentifier);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ((isRootCommand && !def.isRootCommand()) || (!isRootCommand && def.isRootCommand())) {
 | 
					 | 
				
			||||||
            throw new IllegalArgumentException(def + ": cannot have subcommands and rootcommand definitions together");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        executableDefinitons.add(def);
 | 
					 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SubCommandGroup[] getSubCommandGroups() {
 | 
					    public SlashCommandIdentifier[] getSubCommandGroups() {
 | 
				
			||||||
        List<SubCommandGroup> subCommandGroups = Arrays.stream(getExecutableDefinitons())
 | 
					        if (isRootCommand)
 | 
				
			||||||
            .filter((x) -> x.subCommandGroup() != null)
 | 
					            return null;
 | 
				
			||||||
            .map((x) -> x.subCommandGroup())
 | 
					        
 | 
				
			||||||
 | 
					        List<InteractionIdentifier> subCommandGroups = entries().stream()
 | 
				
			||||||
 | 
					            .filter(x -> x.parent().parent() != null)
 | 
				
			||||||
 | 
					            .map(x -> x.parent())
 | 
				
			||||||
            .toList();
 | 
					            .toList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        HashMap<String, SubCommandGroup> subCommandGroupMap = new HashMap<>();
 | 
					        return subCommandGroups.toArray(SlashCommandIdentifier[]::new);
 | 
				
			||||||
        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(new SubCommandGroup[0]);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SubCommand[] getSubCommands(String groupName) {
 | 
					    public SlashCommandIdentifier[] getSubCommands() {
 | 
				
			||||||
        List<SubCommand> subCommands;
 | 
					        if (isRootCommand)
 | 
				
			||||||
        if (groupName == null)
 | 
					            return null;
 | 
				
			||||||
            subCommands = Arrays.stream(getExecutableDefinitons())
 | 
					        return entries.stream().filter(x -> x.parent() instanceof RootCommandIdentifier).toArray(SlashCommandIdentifier[]::new);
 | 
				
			||||||
            .filter((x) -> x.subCommandGroup() == null && x.subCommand() != null)
 | 
					    }
 | 
				
			||||||
            .map((x) -> x.subCommand())
 | 
					
 | 
				
			||||||
            .toList();
 | 
					    public SlashCommandIdentifier[] getSubCommands(String groupName) {
 | 
				
			||||||
        else 
 | 
					        if (isRootCommand)
 | 
				
			||||||
            subCommands = Arrays.stream(getExecutableDefinitons())
 | 
					            return null;
 | 
				
			||||||
            .filter((x) -> x.subCommandGroup().name().equals(groupName) && x.subCommand() != null)
 | 
					
 | 
				
			||||||
            .map((x) -> x.subCommand())
 | 
					        List<InteractionIdentifier> subCommands = entries().stream()
 | 
				
			||||||
 | 
					            .filter(x -> x.parent().parent() != null && x.parent().name().equals(groupName))
 | 
				
			||||||
 | 
					            .map(x -> x.parent().parent())
 | 
				
			||||||
            .toList();
 | 
					            .toList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        HashMap<String, SubCommand> subCommandMap = new HashMap<>();
 | 
					        return subCommands.toArray(SlashCommandIdentifier[]::new);
 | 
				
			||||||
        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(new SubCommand[0]);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SlashCommand getFullSlashCommand() {
 | 
					    @Override
 | 
				
			||||||
        if (isRootCommand())
 | 
					    public boolean equals(Object obj) {
 | 
				
			||||||
            return getSlashCommand();
 | 
					        if (!(obj instanceof SlashCommandDefinition))
 | 
				
			||||||
        for (ExecutableSlashCommandDefinition executableSlashCommandDefinition : executableDefinitons) {
 | 
					            return false;
 | 
				
			||||||
            if (executableSlashCommandDefinition.options().length > 0)
 | 
					        SlashCommandDefinition other = (SlashCommandDefinition) obj;
 | 
				
			||||||
                return executableSlashCommandDefinition.applicationCommand();
 | 
					        return this.rootIdentifier().equals(other.rootIdentifier());
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SlashCommand getSlashCommand() {
 | 
					    public long[] serverIds() {
 | 
				
			||||||
        return slashCommand;
 | 
					        return rootIdentifier().serverIds();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ExecutableSlashCommandDefinition[] getExecutableDefinitons() {
 | 
					    public Set<InteractionIdentifier> entries() {
 | 
				
			||||||
        return executableDefinitons.toArray(new ExecutableSlashCommandDefinition[0]);
 | 
					        return this.entries;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public RootCommandIdentifier rootIdentifier() {
 | 
				
			||||||
 | 
					        return rootIdentifier;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean isRootCommand() {
 | 
					    public boolean isRootCommand() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
package net.tomatentum.marinara.interaction.commands;
 | 
					package net.tomatentum.marinara.interaction.commands.choice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public interface ChoiceValueProvider<T> {
 | 
					public interface ChoiceValueProvider<T> {
 | 
				
			||||||
    T getChoiceValue();
 | 
					    T getChoiceValue();
 | 
				
			||||||
@@ -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.InvocationTargetException;
 | 
				
			||||||
import java.lang.reflect.Method;
 | 
					import java.lang.reflect.Method;
 | 
				
			||||||
@@ -0,0 +1,141 @@
 | 
				
			|||||||
 | 
					package net.tomatentum.marinara.interaction.ident;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					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 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private long[] serverIds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public RootCommandIdentifier(
 | 
				
			||||||
 | 
					            InteractionIdentifier parent, 
 | 
				
			||||||
 | 
					            String name, 
 | 
				
			||||||
 | 
					            String description, 
 | 
				
			||||||
 | 
					            InteractionType type,
 | 
				
			||||||
 | 
					            SlashCommandOption[] options, 
 | 
				
			||||||
 | 
					            long[] serverIds) {
 | 
				
			||||||
 | 
					        super(parent, name, description, type, options);
 | 
				
			||||||
 | 
					        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 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 long[] serverIds() {
 | 
				
			||||||
 | 
					            return this.serverIds;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Builder serverIds(long[] serverIds) {
 | 
				
			||||||
 | 
					            this.serverIds = serverIds;
 | 
				
			||||||
 | 
					            return this;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public SlashCommandIdentifier build(boolean autocomplete) {
 | 
				
			||||||
 | 
					            return new RootCommandIdentifier(
 | 
				
			||||||
 | 
					                parent, 
 | 
				
			||||||
 | 
					                name, 
 | 
				
			||||||
 | 
					                description, 
 | 
				
			||||||
 | 
					                autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND, 
 | 
				
			||||||
 | 
					                options, 
 | 
				
			||||||
 | 
					                serverIds);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					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,
 | 
				
			||||||
 | 
					            InteractionType type,
 | 
				
			||||||
 | 
					            SlashCommandOption[] options
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					        super(parent, name, description, type);
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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 SlashCommandIdentifier build(boolean autocomplete) {
 | 
				
			||||||
 | 
					            return new SlashCommandIdentifier(
 | 
				
			||||||
 | 
					                parent, 
 | 
				
			||||||
 | 
					                name, 
 | 
				
			||||||
 | 
					                description, 
 | 
				
			||||||
 | 
					                autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND, 
 | 
				
			||||||
 | 
					                options);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,14 +4,13 @@ import java.lang.reflect.Method;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import net.tomatentum.marinara.Marinara;
 | 
					import net.tomatentum.marinara.Marinara;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
					import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionType;
 | 
					import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.parser.AnnotationParser;
 | 
					import net.tomatentum.marinara.parser.AnnotationParser;
 | 
				
			||||||
import net.tomatentum.marinara.parser.SlashCommandParser;
 | 
					import net.tomatentum.marinara.parser.SlashCommandParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class AutoCompleteInteractionMethod extends InteractionMethod {
 | 
					public class AutoCompleteInteractionMethod extends InteractionMethod {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private ExecutableSlashCommandDefinition commandDefinition;
 | 
					    private InteractionIdentifier interactionIdentifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public AutoCompleteInteractionMethod(Method method, 
 | 
					    public AutoCompleteInteractionMethod(Method method, 
 | 
				
			||||||
        InteractionHandler handler, 
 | 
					        InteractionHandler handler, 
 | 
				
			||||||
@@ -21,31 +20,25 @@ public class AutoCompleteInteractionMethod extends InteractionMethod {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public AnnotationParser[] getParsers() {
 | 
					    public AnnotationParser[] parsers() {
 | 
				
			||||||
        return new AnnotationParser[] { 
 | 
					        return new AnnotationParser[] { 
 | 
				
			||||||
            new SlashCommandParser(method, (x) -> { this.commandDefinition = x; } ) 
 | 
					            new SlashCommandParser(method, true, (x) -> { this.interactionIdentifier = x; } ) 
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Object getParameter(Object context, int index) {
 | 
					    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);
 | 
					        Object autocompleteOptionValue = marinara.getWrapper().getContextObjectProvider().getAutocompleteFocusedOption(context);
 | 
				
			||||||
        if (autocompleteOptionValue != null)
 | 
					        if (autocompleteOptionValue != null)
 | 
				
			||||||
            return autocompleteOptionValue;
 | 
					            return autocompleteOptionValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return marinara.getWrapper().getContextObjectProvider().getComponentContextObject(context, type);
 | 
					        return marinara.getWrapper().getContextObjectProvider().getInteractionContextObject(context, type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean canRun(Object context) {
 | 
					    public InteractionIdentifier identifier() {
 | 
				
			||||||
        ExecutableSlashCommandDefinition other = marinara.getWrapper().getCommandDefinition(context);
 | 
					        return interactionIdentifier;
 | 
				
			||||||
        return commandDefinition.equals(other);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public InteractionType getType() {
 | 
					 | 
				
			||||||
        return InteractionType.AUTOCOMPLETE;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ import java.lang.reflect.Method;
 | 
				
			|||||||
import net.tomatentum.marinara.Marinara;
 | 
					import net.tomatentum.marinara.Marinara;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
					import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionType;
 | 
					import net.tomatentum.marinara.interaction.InteractionType;
 | 
				
			||||||
 | 
					import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
 | 
				
			||||||
import net.tomatentum.marinara.parser.AnnotationParser;
 | 
					import net.tomatentum.marinara.parser.AnnotationParser;
 | 
				
			||||||
import net.tomatentum.marinara.parser.ButtonParser;
 | 
					import net.tomatentum.marinara.parser.ButtonParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -17,7 +18,7 @@ public class ButtonInteractionMethod extends InteractionMethod {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public AnnotationParser[] getParsers() {
 | 
					    public AnnotationParser[] parsers() {
 | 
				
			||||||
        return new AnnotationParser[] {
 | 
					        return new AnnotationParser[] {
 | 
				
			||||||
            new ButtonParser(method, (x) -> { this.customId = x; } )
 | 
					            new ButtonParser(method, (x) -> { this.customId = x; } )
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
@@ -25,18 +26,17 @@ public class ButtonInteractionMethod extends InteractionMethod {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Object getParameter(Object context, int index) {
 | 
					    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);
 | 
					        return marinara.getWrapper().getContextObjectProvider().getComponentContextObject(context, type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean canRun(Object context) {
 | 
					    public InteractionIdentifier identifier() {
 | 
				
			||||||
        return marinara.getWrapper().getButtonId(context).equals(customId);
 | 
					        return InteractionIdentifier.builder()
 | 
				
			||||||
    }
 | 
					            .name(customId)
 | 
				
			||||||
 | 
					            .description("Button")
 | 
				
			||||||
    @Override
 | 
					            .type(InteractionType.BUTTON)
 | 
				
			||||||
    public InteractionType getType() {
 | 
					            .build();
 | 
				
			||||||
        return InteractionType.BUTTON;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,11 +12,11 @@ import org.apache.logging.log4j.Logger;
 | 
				
			|||||||
import net.tomatentum.marinara.Marinara;
 | 
					import net.tomatentum.marinara.Marinara;
 | 
				
			||||||
import net.tomatentum.marinara.checks.AppliedCheck;
 | 
					import net.tomatentum.marinara.checks.AppliedCheck;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
					import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionType;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.annotation.AutoComplete;
 | 
					import net.tomatentum.marinara.interaction.annotation.AutoComplete;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.annotation.Button;
 | 
					import net.tomatentum.marinara.interaction.annotation.Button;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
 | 
					import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
 | 
					import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
 | 
				
			||||||
 | 
					import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
 | 
				
			||||||
import net.tomatentum.marinara.parser.AnnotationParser;
 | 
					import net.tomatentum.marinara.parser.AnnotationParser;
 | 
				
			||||||
import net.tomatentum.marinara.parser.InteractionCheckParser;
 | 
					import net.tomatentum.marinara.parser.InteractionCheckParser;
 | 
				
			||||||
import net.tomatentum.marinara.util.LoggerUtil;
 | 
					import net.tomatentum.marinara.util.LoggerUtil;
 | 
				
			||||||
@@ -42,7 +42,8 @@ public abstract class InteractionMethod {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
					    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected InteractionMethod(Method method, 
 | 
					    protected InteractionMethod(
 | 
				
			||||||
 | 
					        Method method, 
 | 
				
			||||||
        InteractionHandler handler, 
 | 
					        InteractionHandler handler, 
 | 
				
			||||||
        Marinara marinara
 | 
					        Marinara marinara
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
@@ -52,7 +53,7 @@ public abstract class InteractionMethod {
 | 
				
			|||||||
        this.method = method;
 | 
					        this.method = method;
 | 
				
			||||||
        this.handler = handler;
 | 
					        this.handler = handler;
 | 
				
			||||||
        this.marinara = marinara;
 | 
					        this.marinara = marinara;
 | 
				
			||||||
        this.parsers = new ArrayList<>(Arrays.asList(getParsers()));
 | 
					        this.parsers = new ArrayList<>(Arrays.asList(parsers()));
 | 
				
			||||||
        this.appliedChecks = new ArrayList<>();
 | 
					        this.appliedChecks = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        parsers.add(new InteractionCheckParser(method, appliedChecks::add, marinara.getCheckRegistry()));
 | 
					        parsers.add(new InteractionCheckParser(method, appliedChecks::add, marinara.getCheckRegistry()));
 | 
				
			||||||
@@ -60,14 +61,6 @@ public abstract class InteractionMethod {
 | 
				
			|||||||
        parsers.stream().forEach(AnnotationParser::parse);
 | 
					        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) {
 | 
					    public void run(Object context) {
 | 
				
			||||||
        if (this.appliedChecks.stream().filter(x -> !x.pre(context)).count() > 0)
 | 
					        if (this.appliedChecks.stream().filter(x -> !x.pre(context)).count() > 0)
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@@ -82,7 +75,13 @@ public abstract class InteractionMethod {
 | 
				
			|||||||
        this.appliedChecks.forEach(x -> x.post(context));
 | 
					        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;
 | 
					        return method;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,48 +4,34 @@ import java.lang.reflect.Method;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import net.tomatentum.marinara.Marinara;
 | 
					import net.tomatentum.marinara.Marinara;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
					import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionType;
 | 
					import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition;
 | 
					import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
 | 
				
			||||||
import net.tomatentum.marinara.parser.AnnotationParser;
 | 
					import net.tomatentum.marinara.parser.AnnotationParser;
 | 
				
			||||||
import net.tomatentum.marinara.parser.SlashCommandParser;
 | 
					import net.tomatentum.marinara.parser.SlashCommandParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class SlashCommandInteractionMethod extends InteractionMethod {
 | 
					public class SlashCommandInteractionMethod extends InteractionMethod {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private ExecutableSlashCommandDefinition commandDefinition;
 | 
					    private SlashCommandIdentifier interactionIdentifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SlashCommandInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) {
 | 
					    SlashCommandInteractionMethod(Method method, InteractionHandler handler, Marinara marinara) {
 | 
				
			||||||
        super(method, handler, marinara);
 | 
					        super(method, handler, marinara);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public AnnotationParser[] getParsers() {
 | 
					    public AnnotationParser[] parsers() {
 | 
				
			||||||
        return new AnnotationParser[] { 
 | 
					        return new AnnotationParser[] { 
 | 
				
			||||||
            new SlashCommandParser(method, (x) -> { this.commandDefinition = x; } ) 
 | 
					            new SlashCommandParser(method, false, (x) -> { this.interactionIdentifier = x; } ) 
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Object getParameter(Object context, int index) {
 | 
					    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
 | 
					    @Override
 | 
				
			||||||
    public boolean canRun(Object context) {
 | 
					    public InteractionIdentifier identifier() {
 | 
				
			||||||
        ExecutableSlashCommandDefinition other = marinara.getWrapper().getCommandDefinition(context);
 | 
					        return interactionIdentifier;
 | 
				
			||||||
        return commandDefinition.equals(other);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public InteractionType getType() {
 | 
					 | 
				
			||||||
        return InteractionType.COMMAND;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public ExecutableSlashCommandDefinition getCommandDefinition() {
 | 
					 | 
				
			||||||
        return commandDefinition;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setCommandDefinition(ExecutableSlashCommandDefinition commandDefinition) {
 | 
					 | 
				
			||||||
        this.commandDefinition = commandDefinition;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,22 +5,26 @@ import java.util.function.Consumer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import org.apache.logging.log4j.Logger;
 | 
					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.SlashCommand;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
 | 
					import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
 | 
					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.LoggerUtil;
 | 
				
			||||||
import net.tomatentum.marinara.util.ReflectionUtil;
 | 
					import net.tomatentum.marinara.util.ReflectionUtil;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class SlashCommandParser implements AnnotationParser {
 | 
					public class SlashCommandParser implements AnnotationParser {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Method method;
 | 
					    private Method method;
 | 
				
			||||||
    private Consumer<ExecutableSlashCommandDefinition> consumer;
 | 
					    private boolean isAutoComplete;
 | 
				
			||||||
 | 
					    private Consumer<SlashCommandIdentifier> consumer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
					    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SlashCommandParser(Method method, Consumer<ExecutableSlashCommandDefinition> consumer) {
 | 
					    public SlashCommandParser(Method method, boolean isAutoComplete, Consumer<SlashCommandIdentifier> consumer) {
 | 
				
			||||||
        this.method = method;
 | 
					        this.method = method;
 | 
				
			||||||
 | 
					        this.isAutoComplete = isAutoComplete;
 | 
				
			||||||
        this.consumer = consumer;
 | 
					        this.consumer = consumer;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,23 +33,34 @@ public class SlashCommandParser implements AnnotationParser {
 | 
				
			|||||||
        this.checkValidCommandMethod(method);
 | 
					        this.checkValidCommandMethod(method);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SlashCommand cmd = ReflectionUtil.getAnnotation(method, SlashCommand.class);
 | 
					        SlashCommand cmd = ReflectionUtil.getAnnotation(method, SlashCommand.class);
 | 
				
			||||||
        ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder();
 | 
					        InteractionIdentifier lastIdentifier = InteractionIdentifier.rootBuilder()
 | 
				
			||||||
        builder.setApplicationCommand(cmd);
 | 
					            .name(cmd.name())
 | 
				
			||||||
 | 
					            .description(cmd.description())
 | 
				
			||||||
 | 
					            .options(cmd.options())
 | 
				
			||||||
 | 
					            .serverIds(cmd.serverIds())
 | 
				
			||||||
 | 
					            .build(isAutoComplete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) {
 | 
					        if (ReflectionUtil.isAnnotationPresent(method, SubCommandGroup.class)) {
 | 
				
			||||||
            SubCommandGroup cmdGroup = ReflectionUtil.getAnnotation(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)) {
 | 
					        if (ReflectionUtil.isAnnotationPresent(method, SubCommand.class)) {
 | 
				
			||||||
            SubCommand subCmd = ReflectionUtil.getAnnotation(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())
 | 
				
			||||||
 | 
					                .build(isAutoComplete);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ExecutableSlashCommandDefinition def = builder.build();
 | 
					        logger.trace("Parsed using SlashCommandParser for method {} with the result:\n{}", ReflectionUtil.getFullMethodName(method), lastIdentifier.toString());
 | 
				
			||||||
 | 
					        consumer.accept((SlashCommandIdentifier) lastIdentifier);
 | 
				
			||||||
        logger.trace("Parsed using SlashCommandParser for method {} with the result:\n{}", ReflectionUtil.getFullMethodName(method), def.toString());
 | 
					 | 
				
			||||||
        consumer.accept(builder.build());
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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<InteractionMethod> 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<InteractionMethod> methods() {
 | 
				
			||||||
 | 
					        return methods;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,9 +1,11 @@
 | 
				
			|||||||
package net.tomatentum.marinara.registry;
 | 
					package net.tomatentum.marinara.registry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.lang.reflect.Method;
 | 
					import java.lang.reflect.Method;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.Arrays;
 | 
				
			||||||
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.logging.log4j.Logger;
 | 
					import org.apache.logging.log4j.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,67 +13,68 @@ import net.tomatentum.marinara.Marinara;
 | 
				
			|||||||
import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
					import net.tomatentum.marinara.interaction.InteractionHandler;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionType;
 | 
					import net.tomatentum.marinara.interaction.InteractionType;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
 | 
					import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition;
 | 
					import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
 | 
				
			||||||
import net.tomatentum.marinara.interaction.methods.SlashCommandInteractionMethod;
 | 
					import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
 | 
				
			||||||
import net.tomatentum.marinara.util.LoggerUtil;
 | 
					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;
 | 
					import net.tomatentum.marinara.interaction.methods.InteractionMethod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class InteractionRegistry {
 | 
					public class InteractionRegistry {
 | 
				
			||||||
    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
					    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
				
			||||||
    private List<InteractionMethod> interactionMethods;
 | 
					    private Set<InteractionEntry> interactions;
 | 
				
			||||||
    private Marinara marinara;
 | 
					    private Marinara marinara;
 | 
				
			||||||
 | 
					    private IdentifierProvider identifierProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public InteractionRegistry(Marinara marinara) {
 | 
					    public InteractionRegistry(Marinara marinara) {
 | 
				
			||||||
        this.interactionMethods = new ArrayList<>();
 | 
					        this.interactions = new HashSet<>();
 | 
				
			||||||
        this.marinara = marinara;
 | 
					        this.marinara = marinara;
 | 
				
			||||||
 | 
					        this.identifierProvider = marinara.getWrapper().createIdentifierProvider();
 | 
				
			||||||
        marinara.getWrapper().subscribeInteractions(this::handle);
 | 
					        marinara.getWrapper().subscribeInteractions(this::handle);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * TODO: Maybe relocate InteractionEntry checking to another class with description merging.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public void addInteractions(InteractionHandler interactionHandler) {
 | 
					    public void addInteractions(InteractionHandler interactionHandler) {
 | 
				
			||||||
        for (Method method : interactionHandler.getClass().getMethods()) {
 | 
					        for (Method method : interactionHandler.getClass().getMethods()) {
 | 
				
			||||||
            InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, marinara);
 | 
					            InteractionMethod iMethod = InteractionMethod.create(method, interactionHandler, marinara);
 | 
				
			||||||
            if (iMethod != null) {
 | 
					            if (iMethod != null) {
 | 
				
			||||||
                this.interactionMethods.add(iMethod);
 | 
					                Optional<InteractionEntry> oentry = this.interactions.stream()
 | 
				
			||||||
                logger.debug("Added {} method from {}", iMethod.getMethod().getName(), interactionHandler.getClass().getSimpleName());
 | 
					                    .filter(i -> i.identifier().equals(iMethod.identifier()))
 | 
				
			||||||
 | 
					                    .findFirst();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                InteractionEntry entry = oentry.orElse(new InteractionEntry(iMethod.identifier())).addMethod(iMethod);
 | 
				
			||||||
 | 
					                if (oentry.isEmpty()) this.interactions.add(entry);
 | 
				
			||||||
 | 
					                logger.debug("Added {} method from {}", iMethod.method().getName(), interactionHandler.getClass().getSimpleName());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        logger.info("Added all Interactions from {}", interactionHandler.getClass().getSimpleName());
 | 
					        logger.info("Added all Interactions from {}", interactionHandler.getClass().getSimpleName());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void registerCommands() {
 | 
					    public void registerCommands() {
 | 
				
			||||||
        List<SlashCommandDefinition> defs = new ArrayList<>();
 | 
					        List<InteractionIdentifier> slashIdentifiers = interactions.stream()
 | 
				
			||||||
        List<ExecutableSlashCommandDefinition> execDefs = interactionMethods.stream()
 | 
					            .filter((x) -> x.type().equals(InteractionType.COMMAND))
 | 
				
			||||||
            .filter((x) -> x.getClass().isAssignableFrom(SlashCommandInteractionMethod.class))
 | 
					            .map((x) -> x.identifier())
 | 
				
			||||||
            .map((x) -> ((SlashCommandInteractionMethod)x).getCommandDefinition())
 | 
					 | 
				
			||||||
            .toList();
 | 
					            .toList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        execDefs.forEach((def) -> {
 | 
					        SlashCommandDefinition[] defs = new ObjectAggregator<InteractionIdentifier, RootCommandIdentifier, SlashCommandDefinition>(
 | 
				
			||||||
            Optional<SlashCommandDefinition> appDef = defs.stream()
 | 
					            i -> Arrays.asList((RootCommandIdentifier)i.rootNode()),
 | 
				
			||||||
                .filter((x) -> x.getSlashCommand().equals(def.applicationCommand()))
 | 
					            SlashCommandDefinition::addIdentifier,
 | 
				
			||||||
                .findFirst();
 | 
					            SlashCommandDefinition::new)
 | 
				
			||||||
            if (appDef.isPresent())
 | 
					            .aggregate(slashIdentifiers)
 | 
				
			||||||
                appDef.get().addExecutableCommand(def);
 | 
					            .toArray(SlashCommandDefinition[]::new);
 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                defs.add(new SlashCommandDefinition(def.applicationCommand()).addExecutableCommand(def));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            logger.debug("Added Executable Command {}{}{} for registration", 
 | 
					        marinara.getWrapper().getRegisterer().register(defs);
 | 
				
			||||||
                def.applicationCommand().name(), 
 | 
					 | 
				
			||||||
                def.subCommandGroup() == null ? "" : "." + def.subCommandGroup().name(),
 | 
					 | 
				
			||||||
                def.subCommand() == null ? "" : "." + def.subCommand().name()
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        marinara.getWrapper().registerSlashCommands(defs.toArray(SlashCommandDefinition[]::new));
 | 
					 | 
				
			||||||
        logger.info("Registered all SlashCommands");
 | 
					        logger.info("Registered all SlashCommands");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void handle(Object context) {
 | 
					    public void handle(Object context) {
 | 
				
			||||||
        InteractionType type = marinara.getWrapper().getInteractionType(context);
 | 
					 | 
				
			||||||
        logger.debug("Received {} interaction ", context);
 | 
					        logger.debug("Received {} interaction ", context);
 | 
				
			||||||
        interactionMethods.forEach((m) -> {
 | 
					        interactions.forEach((e) -> {
 | 
				
			||||||
            if (m.getType().equals(type) && m.canRun(context)) {
 | 
					            if (this.identifierProvider.provide(context).equals(e.identifier())) {
 | 
				
			||||||
                logger.info("Running {} interaction using {}\ncontext: {}", type, m.getMethod().toString(), context.toString());
 | 
					                logger.info("Running {} interaction using {}\ncontext: {}", e.type(), e.toString(), context.toString());
 | 
				
			||||||
                m.run(context);
 | 
					                e.runAll(context);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					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;
 | 
				
			||||||
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ObjectAggregator<O, K, V> {
 | 
				
			||||||
 | 
					    private Function<O, Iterable<K>> keySupplier;
 | 
				
			||||||
 | 
					    private BiConsumer<V, O> valueConsumer;
 | 
				
			||||||
 | 
					    private Function<K, V> defaultGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ObjectAggregator(
 | 
				
			||||||
 | 
					            Function<O, Iterable<K>> keySupplier, 
 | 
				
			||||||
 | 
					            BiConsumer<V, O> valueConsumer, 
 | 
				
			||||||
 | 
					            Function<K, V> defaultGenerator) {
 | 
				
			||||||
 | 
					        this.keySupplier = keySupplier;
 | 
				
			||||||
 | 
					        this.valueConsumer = valueConsumer;
 | 
				
			||||||
 | 
					        this.defaultGenerator = defaultGenerator;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ObjectAggregator(
 | 
				
			||||||
 | 
					            Function<O, Iterable<K>> keySupplier, 
 | 
				
			||||||
 | 
					            BiConsumer<V, O> valueConsumer, 
 | 
				
			||||||
 | 
					            Supplier<V> defaultGenerator) {
 | 
				
			||||||
 | 
					        this.keySupplier = keySupplier;
 | 
				
			||||||
 | 
					        this.valueConsumer = valueConsumer;
 | 
				
			||||||
 | 
					        this.defaultGenerator = _ -> defaultGenerator.get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Collection<V> aggregate(Iterable<O> iterator) {
 | 
				
			||||||
 | 
					        Map<K, V> map = new HashMap<>();
 | 
				
			||||||
 | 
					        for (O element : iterator) {
 | 
				
			||||||
 | 
					            Iterable<K> 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();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package net.tomatentum.marinara.util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ObjectListAggregator<O, K, V> extends ObjectAggregator<O, K, ArrayList<V>> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ObjectListAggregator(Function<O, Iterable<K>> keySupplier, Function<O, V> valueConsumer) {
 | 
				
			||||||
 | 
					        super(keySupplier, 
 | 
				
			||||||
 | 
					        (l, o) -> l.add(valueConsumer.apply(o)),
 | 
				
			||||||
 | 
					        () -> new ArrayList<>());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					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;
 | 
				
			||||||
 | 
					import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
 | 
				
			||||||
 | 
					import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class CommandConverter<A extends Object, O extends Object, C extends Object> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static <A, O, C> CommandConverter<A, O, C> of(Spec<A, O, C> spec) {
 | 
				
			||||||
 | 
					        return new CommandConverter<>(spec);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Spec<A, O, C> spec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CommandConverter(Spec<A, O, C> spec) {
 | 
				
			||||||
 | 
					        this.spec = spec;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public A convert(SlashCommandDefinition def) {
 | 
				
			||||||
 | 
					        List<O> 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<O> convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommand).toList();
 | 
				
			||||||
 | 
					        return spec.convertSubCommandGroup(identifier, convertedSubCommands);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private O convertSubCommand(SlashCommandIdentifier identifier) {
 | 
				
			||||||
 | 
					        List<O> options = Arrays.stream(identifier.options()).map(this::convertOption).toList();
 | 
				
			||||||
 | 
					        return spec.convertSubCommand(identifier, options);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private O convertOption(SlashCommandOption option) {
 | 
				
			||||||
 | 
					        List<C> choices = Arrays.stream(SlashCommandDefinition.getActualChoices(option)).map(spec::convertChoice).toList();
 | 
				
			||||||
 | 
					        return spec.convertOption(option, choices);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static interface Spec<A extends Object, O extends Object, C extends Object> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public A convertCommand(RootCommandIdentifier rootIdentifier, List<O>  options);
 | 
				
			||||||
 | 
					        public O convertSubCommandGroup(InteractionIdentifier identifier, List<O> subCommands);
 | 
				
			||||||
 | 
					        public O convertSubCommand(InteractionIdentifier identifier, List<O>  options);
 | 
				
			||||||
 | 
					        public O convertOption(SlashCommandOption option, List<C> choices);
 | 
				
			||||||
 | 
					        public C convertChoice(SlashCommandOptionChoice choice);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<A extends Object> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static <A extends Object> CommandRegisterer<A> of(Strategy<A> strategy, CommandConverter<A, ?, ?> converter) {
 | 
				
			||||||
 | 
					        return new CommandRegisterer<A>(strategy, converter);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Strategy<A> strategy;
 | 
				
			||||||
 | 
					    private CommandConverter<A, ?, ?> converter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CommandRegisterer(Strategy<A> strategy, CommandConverter<A, ?, ?> converter) {
 | 
				
			||||||
 | 
					        this.strategy = strategy;
 | 
				
			||||||
 | 
					        this.converter = converter;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void register(SlashCommandDefinition[] slashDefs) {
 | 
				
			||||||
 | 
					        Set<ServerCommandList<A>> serverCommands = new ObjectAggregator<SlashCommandDefinition, Long, ServerCommandList<A>>(
 | 
				
			||||||
 | 
					                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<A> 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<A extends Object> {
 | 
				
			||||||
 | 
					        void registerServer(ServerCommandList<A> commands);
 | 
				
			||||||
 | 
					        void registerGlobal(Set<A> defs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<Class<?>, Converter<?>> converter;
 | 
				
			||||||
 | 
					    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IdentifierProvider(List<Converter<?>> 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<Object> conv = (Converter<Object>) converter.get(type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return conv.convert(context);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @FunctionalInterface
 | 
				
			||||||
 | 
					    public interface Converter<T extends Object> {
 | 
				
			||||||
 | 
					        InteractionIdentifier convert(T context);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static class LambdaWrapper<T extends Object> implements Converter<T> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private Converter<T> converter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        LambdaWrapper(Converter<T> converter) {
 | 
				
			||||||
 | 
					            this.converter = converter;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public InteractionIdentifier convert(T context) {
 | 
				
			||||||
 | 
					            return this.converter.convert(context);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,17 +3,12 @@ package net.tomatentum.marinara.wrapper;
 | 
				
			|||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.function.Consumer;
 | 
					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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public abstract class LibraryWrapper {
 | 
					public abstract class LibraryWrapper {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private List<Consumer<Object>> interactionSubscriber;
 | 
					    private List<Consumer<Object>> interactionSubscriber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected LibraryWrapper() {
 | 
					    protected LibraryWrapper() {
 | 
				
			||||||
        interactionSubscriber = new ArrayList<>();
 | 
					        this.interactionSubscriber = new ArrayList<>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void handleInteraction(Object context) {
 | 
					    public void handleInteraction(Object context) {
 | 
				
			||||||
@@ -27,13 +22,8 @@ public abstract class LibraryWrapper {
 | 
				
			|||||||
        interactionSubscriber.remove(consumer);
 | 
					        interactionSubscriber.remove(consumer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract InteractionType getInteractionType(Object context);
 | 
					    public abstract CommandRegisterer<?> getRegisterer();  
 | 
				
			||||||
 | 
					    public abstract IdentifierProvider createIdentifierProvider();
 | 
				
			||||||
    public abstract void registerSlashCommands(SlashCommandDefinition[] defs); 
 | 
					 | 
				
			||||||
    public abstract ExecutableSlashCommandDefinition getCommandDefinition(Object context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public abstract String getButtonId(Object context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public abstract ContextObjectProvider getContextObjectProvider();
 | 
					    public abstract ContextObjectProvider getContextObjectProvider();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package net.tomatentum.marinara.wrapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.HashSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ServerCommandList<A> extends HashSet<A>{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private long serverId;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public ServerCommandList(long serverId) {
 | 
				
			||||||
 | 
					        this.serverId = serverId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public long serverId() {
 | 
				
			||||||
 | 
					        return serverId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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.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<ApplicationCommandRequest, ApplicationCommandOptionData, ApplicationCommandOptionChoiceData> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public ApplicationCommandRequest convertCommand(RootCommandIdentifier rootIdentifier,
 | 
				
			||||||
 | 
								List<ApplicationCommandOptionData> options) {
 | 
				
			||||||
 | 
					        return ApplicationCommandRequest.builder()
 | 
				
			||||||
 | 
					            .name(rootIdentifier.name())
 | 
				
			||||||
 | 
					            .description(rootIdentifier.description())
 | 
				
			||||||
 | 
					            .options(options)
 | 
				
			||||||
 | 
					            .build();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public ApplicationCommandOptionData convertSubCommandGroup(InteractionIdentifier identifier,
 | 
				
			||||||
 | 
								List<ApplicationCommandOptionData> 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<ApplicationCommandOptionData> 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<ApplicationCommandOptionChoiceData> 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();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<ApplicationCommandRequest> {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    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<ApplicationCommandRequest> commands) {
 | 
				
			||||||
 | 
					        appService.bulkOverwriteGuildApplicationCommand(applicationId, commands.serverId(), new ArrayList<>(commands));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void registerGlobal(Set<ApplicationCommandRequest> defs) {
 | 
				
			||||||
 | 
					        appService.bulkOverwriteGlobalApplicationCommand(applicationId, new ArrayList<>(defs));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,38 +1,25 @@
 | 
				
			|||||||
package net.tomatentum.marinara.wrapper.discord4j;
 | 
					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.List;
 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.function.Function;
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.logging.log4j.Logger;
 | 
					import org.apache.logging.log4j.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import discord4j.core.GatewayDiscordClient;
 | 
					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.event.domain.interaction.InteractionCreateEvent;
 | 
				
			||||||
import discord4j.core.object.command.ApplicationCommandInteractionOption;
 | 
					import discord4j.core.object.command.ApplicationCommandInteractionOption;
 | 
				
			||||||
import discord4j.core.object.command.ApplicationCommandOption.Type;
 | 
					import discord4j.core.object.command.ApplicationCommandOption.Type;
 | 
				
			||||||
import discord4j.discordjson.json.ApplicationCommandOptionChoiceData;
 | 
					 | 
				
			||||||
import discord4j.discordjson.json.ApplicationCommandOptionData;
 | 
					 | 
				
			||||||
import discord4j.discordjson.json.ApplicationCommandRequest;
 | 
					import discord4j.discordjson.json.ApplicationCommandRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io.leangen.geantyref.AnnotationFormatException;
 | 
					 | 
				
			||||||
import io.leangen.geantyref.TypeFactory;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.InteractionType;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefinition;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
 | 
					 | 
				
			||||||
import net.tomatentum.marinara.util.LoggerUtil;
 | 
					import net.tomatentum.marinara.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.ContextObjectProvider;
 | 
				
			||||||
 | 
					import net.tomatentum.marinara.wrapper.IdentifierProvider;
 | 
				
			||||||
import net.tomatentum.marinara.wrapper.LibraryWrapper;
 | 
					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 {
 | 
					public class Discord4JWrapper extends LibraryWrapper {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,161 +33,37 @@ public class Discord4JWrapper extends LibraryWrapper {
 | 
				
			|||||||
                .filter(o -> !o.getType().equals(Type.SUB_COMMAND) && !o.getType().equals(Type.SUB_COMMAND_GROUP))
 | 
					                .filter(o -> !o.getType().equals(Type.SUB_COMMAND) && !o.getType().equals(Type.SUB_COMMAND_GROUP))
 | 
				
			||||||
                .toList();
 | 
					                .toList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private GatewayDiscordClient api;
 | 
					 | 
				
			||||||
    private Discord4JContextObjectProvider contextObjectProvider;
 | 
					    private Discord4JContextObjectProvider contextObjectProvider;
 | 
				
			||||||
 | 
					    private CommandRegisterer<ApplicationCommandRequest> commandRegisterer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
					    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Discord4JWrapper(GatewayDiscordClient api) {
 | 
					    public Discord4JWrapper(GatewayDiscordClient api) {
 | 
				
			||||||
        this.api = api;
 | 
					 | 
				
			||||||
        this.contextObjectProvider = new Discord4JContextObjectProvider();
 | 
					        this.contextObjectProvider = new Discord4JContextObjectProvider();
 | 
				
			||||||
        if (api != null)
 | 
					        var converter = CommandConverter.of(new Discord4JConverterSpec());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (api != null) {
 | 
				
			||||||
 | 
					            this.commandRegisterer = CommandRegisterer.of(new Discord4JRegistererStrategy(api), converter);
 | 
				
			||||||
            api.on(InteractionCreateEvent.class)
 | 
					            api.on(InteractionCreateEvent.class)
 | 
				
			||||||
                .subscribe(event -> handleInteraction(event));
 | 
					                .subscribe(event -> handleInteraction(event));
 | 
				
			||||||
        else
 | 
					        }else
 | 
				
			||||||
            logger.warn("GatewayDiscordClient was null so no Events were subscribed to.");
 | 
					            logger.warn("GatewayDiscordClient was null so no Events were subscribed to.");
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        logger.info("Discord4J wrapper loaded!");
 | 
					        logger.info("Discord4J wrapper loaded!");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public InteractionType getInteractionType(Object context) {
 | 
					    public CommandRegisterer<?> getRegisterer() {
 | 
				
			||||||
        if (ChatInputAutoCompleteEvent.class.isAssignableFrom(context.getClass()))
 | 
					        return this.commandRegisterer;
 | 
				
			||||||
            return InteractionType.AUTOCOMPLETE;
 | 
					 | 
				
			||||||
        if (ChatInputInteractionEvent.class.isAssignableFrom(context.getClass()))
 | 
					 | 
				
			||||||
            return InteractionType.COMMAND;
 | 
					 | 
				
			||||||
        if (ButtonInteractionEvent.class.isAssignableFrom(context.getClass()))
 | 
					 | 
				
			||||||
            return InteractionType.BUTTON;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void registerSlashCommands(SlashCommandDefinition[] defs) {
 | 
					    public IdentifierProvider createIdentifierProvider() {
 | 
				
			||||||
        HashMap<Long, List<ApplicationCommandRequest>> serverCommands = new HashMap<>();
 | 
					        return IdentifierProvider.of(
 | 
				
			||||||
        List<ApplicationCommandRequest> globalCommands = new ArrayList<>();
 | 
					            new SlashCommandIdentifierConverter(),
 | 
				
			||||||
        long applicationId = api.getRestClient().getApplicationId().block();
 | 
					            new AutocompleteIdentifierConverter(),
 | 
				
			||||||
 | 
					            new ButtonIdentifierConverter()
 | 
				
			||||||
        for (SlashCommandDefinition slashCommandDefinition : defs) {
 | 
					        );
 | 
				
			||||||
            ApplicationCommandRequest request = convertSlashCommand(slashCommandDefinition);
 | 
					 | 
				
			||||||
            if (slashCommandDefinition.getFullSlashCommand().serverIds().length > 0) {
 | 
					 | 
				
			||||||
                for (long serverId : slashCommandDefinition.getFullSlashCommand().serverIds()) {
 | 
					 | 
				
			||||||
                    serverCommands.putIfAbsent(serverId, new ArrayList<>());
 | 
					 | 
				
			||||||
                    serverCommands.get(serverId).add(request);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }else
 | 
					 | 
				
			||||||
                globalCommands.add(request);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (long serverId : serverCommands.keySet()) {
 | 
					 | 
				
			||||||
            api.getRestClient().getApplicationService().bulkOverwriteGuildApplicationCommand(applicationId, serverId, serverCommands.get(serverId));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        api.getRestClient().getApplicationService().bulkOverwriteGlobalApplicationCommand(applicationId, globalCommands);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public ExecutableSlashCommandDefinition getCommandDefinition(Object context) {
 | 
					 | 
				
			||||||
        List<ApplicationCommandInteractionOption> options;
 | 
					 | 
				
			||||||
        String commandName;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (context instanceof ChatInputInteractionEvent) {
 | 
					 | 
				
			||||||
            ChatInputInteractionEvent interaction = (ChatInputInteractionEvent) context;
 | 
					 | 
				
			||||||
            options = SUB_FILTER.apply(interaction.getOptions());
 | 
					 | 
				
			||||||
            commandName = interaction.getCommandName();
 | 
					 | 
				
			||||||
        }else if (context instanceof ChatInputAutoCompleteEvent) {
 | 
					 | 
				
			||||||
            ChatInputAutoCompleteEvent interaction = (ChatInputAutoCompleteEvent) context;
 | 
					 | 
				
			||||||
            options = SUB_FILTER.apply(interaction.getOptions());
 | 
					 | 
				
			||||||
            commandName = interaction.getCommandName();
 | 
					 | 
				
			||||||
        }else
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            builder.setApplicationCommand(TypeFactory.annotation(SlashCommand.class, Map.of("name", commandName)));
 | 
					 | 
				
			||||||
            if (!options.isEmpty()) {
 | 
					 | 
				
			||||||
                if (!ARG_FILTER.apply(options.getFirst().getOptions()).isEmpty()) {
 | 
					 | 
				
			||||||
                    builder.setSubCommandGroup(TypeFactory.annotation(SubCommandGroup.class, Map.of("name", options.getFirst().getName())));
 | 
					 | 
				
			||||||
                    builder.setSubCommand(TypeFactory.annotation(SubCommand.class, Map.of("name", SUB_FILTER.apply(options.getFirst().getOptions()).getFirst().getName())));
 | 
					 | 
				
			||||||
                }else
 | 
					 | 
				
			||||||
                    builder.setSubCommand(TypeFactory.annotation(SubCommand.class, Map.of("name", options.getFirst().getName())));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } catch (AnnotationFormatException e) {
 | 
					 | 
				
			||||||
            logger.fatal(e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return builder.build();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ApplicationCommandRequest convertSlashCommand(SlashCommandDefinition def) {
 | 
					 | 
				
			||||||
        List<ApplicationCommandOptionData> options = new ArrayList<>();
 | 
					 | 
				
			||||||
        SlashCommand cmd = def.getFullSlashCommand();
 | 
					 | 
				
			||||||
        if (!def.isRootCommand()) {
 | 
					 | 
				
			||||||
            Arrays.stream(def.getSubCommands(null)).map(this::convertSubCommandDef).forEach(options::add);
 | 
					 | 
				
			||||||
            Arrays.stream(def.getSubCommandGroups()).map((x) -> convertSubCommandGroupDef(def, x)).forEach(options::add);
 | 
					 | 
				
			||||||
        }else {
 | 
					 | 
				
			||||||
            Arrays.stream(cmd.options()).map(this::convertOptionDef).forEach(options::add);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return ApplicationCommandRequest.builder()
 | 
					 | 
				
			||||||
            .name(cmd.name())
 | 
					 | 
				
			||||||
            .description(cmd.description())
 | 
					 | 
				
			||||||
            .options(options)
 | 
					 | 
				
			||||||
            .build();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ApplicationCommandOptionData convertSubCommandGroupDef(SlashCommandDefinition def, SubCommandGroup subGroup) {
 | 
					 | 
				
			||||||
        SubCommand[] subCommands = def.getSubCommands(subGroup.name());
 | 
					 | 
				
			||||||
        List<ApplicationCommandOptionData> convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommandDef).toList();
 | 
					 | 
				
			||||||
        return ApplicationCommandOptionData.builder()
 | 
					 | 
				
			||||||
            .type(Type.SUB_COMMAND_GROUP.getValue())
 | 
					 | 
				
			||||||
            .name(subGroup.name())
 | 
					 | 
				
			||||||
            .description(subGroup.description())
 | 
					 | 
				
			||||||
            .options(convertedSubCommands)
 | 
					 | 
				
			||||||
            .build();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private ApplicationCommandOptionData convertSubCommandDef(SubCommand sub) {
 | 
					 | 
				
			||||||
        List<ApplicationCommandOptionData> 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<ApplicationCommandOptionChoiceData> convertChoices(SlashCommandOption option) {
 | 
					 | 
				
			||||||
        List<ApplicationCommandOptionChoiceData> convertedChoices = new ArrayList<>();
 | 
					 | 
				
			||||||
        for (SlashCommandOptionChoice choice : ExecutableSlashCommandDefinition.getActualChoices(option)) {
 | 
					 | 
				
			||||||
            var builder = ApplicationCommandOptionChoiceData.builder();
 | 
					 | 
				
			||||||
            builder.name(choice.name());
 | 
					 | 
				
			||||||
            if (choice.longValue() != Long.MAX_VALUE)
 | 
					 | 
				
			||||||
                builder.value(choice.longValue());
 | 
					 | 
				
			||||||
            if (choice.doubleValue() != Double.MAX_VALUE)
 | 
					 | 
				
			||||||
                builder.value(choice.doubleValue());
 | 
					 | 
				
			||||||
            if (!choice.stringValue().isEmpty())
 | 
					 | 
				
			||||||
                builder.value(choice.stringValue());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return convertedChoices;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String getButtonId(Object context) {
 | 
					 | 
				
			||||||
        ButtonInteractionEvent button = (ButtonInteractionEvent) context;
 | 
					 | 
				
			||||||
        return button.getCustomId();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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<ChatInputAutoCompleteEvent> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public InteractionIdentifier convert(ChatInputAutoCompleteEvent context) {
 | 
				
			||||||
 | 
					        List<ApplicationCommandInteractionOption> options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions());
 | 
				
			||||||
 | 
					        String commandName = context.getCommandName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!options.isEmpty()) {
 | 
				
			||||||
 | 
					            List<ApplicationCommandInteractionOption> 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); 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<ButtonInteractionEvent> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public InteractionIdentifier convert(ButtonInteractionEvent context) {
 | 
				
			||||||
 | 
					        return InteractionIdentifier.builder().name(context.getCustomId()).type(InteractionType.BUTTON).build();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<ChatInputInteractionEvent> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public InteractionIdentifier convert(ChatInputInteractionEvent context) {
 | 
				
			||||||
 | 
					        List<ApplicationCommandInteractionOption> options = Discord4JWrapper.SUB_FILTER.apply(context.getOptions());
 | 
				
			||||||
 | 
					        String commandName = context.getCommandName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!options.isEmpty()) {
 | 
				
			||||||
 | 
					            List<ApplicationCommandInteractionOption> 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); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
package net.tomatentum.marinara.test.discord4j;
 | 
					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<String> {
 | 
					public enum TestChoiceEnum implements ChoiceValueProvider<String> {
 | 
				
			||||||
    TestValue("testValue"),
 | 
					    TestValue("testValue"),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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.ident.InteractionIdentifier;
 | 
				
			||||||
 | 
					import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
 | 
				
			||||||
 | 
					import net.tomatentum.marinara.wrapper.CommandConverter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class JavacordConverterSpec implements CommandConverter.Spec<SlashCommandBuilder, SlashCommandOption, SlashCommandOptionChoice> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public SlashCommandBuilder convertCommand(RootCommandIdentifier rootIdentifier, List<SlashCommandOption> options) {
 | 
				
			||||||
 | 
							return SlashCommand.with(rootIdentifier.name(), rootIdentifier.description(), options);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public SlashCommandOption convertSubCommandGroup(InteractionIdentifier identifier,
 | 
				
			||||||
 | 
								List<SlashCommandOption> subCommands) {
 | 
				
			||||||
 | 
							return SlashCommandOption.createWithOptions(
 | 
				
			||||||
 | 
								SlashCommandOptionType.SUB_COMMAND_GROUP, 
 | 
				
			||||||
 | 
								identifier.name(), 
 | 
				
			||||||
 | 
								identifier.description(), 
 | 
				
			||||||
 | 
								subCommands);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public SlashCommandOption convertSubCommand(InteractionIdentifier identifier, List<SlashCommandOption> 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<SlashCommandOptionChoice> 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();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<SlashCommandBuilder> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private DiscordApi api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public JavacordRegistererStrategy(DiscordApi api) {
 | 
				
			||||||
 | 
					        this.api = api;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void registerServer(ServerCommandList<SlashCommandBuilder> commands) {
 | 
				
			||||||
 | 
					        api.bulkOverwriteServerApplicationCommands(commands.serverId(), commands);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void registerGlobal(Set<SlashCommandBuilder> defs) {
 | 
				
			||||||
 | 
					        api.bulkOverwriteGlobalApplicationCommands(defs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,180 +1,50 @@
 | 
				
			|||||||
package net.tomatentum.marinara.wrapper.javacord;
 | 
					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;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.Set;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.apache.logging.log4j.Logger;
 | 
					import org.apache.logging.log4j.Logger;
 | 
				
			||||||
import org.javacord.api.DiscordApi;
 | 
					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;
 | 
					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 io.leangen.geantyref.AnnotationFormatException;
 | 
					import net.tomatentum.marinara.wrapper.CommandConverter;
 | 
				
			||||||
import io.leangen.geantyref.TypeFactory;
 | 
					import net.tomatentum.marinara.wrapper.CommandRegisterer;
 | 
				
			||||||
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.wrapper.ContextObjectProvider;
 | 
					import net.tomatentum.marinara.wrapper.ContextObjectProvider;
 | 
				
			||||||
 | 
					import net.tomatentum.marinara.wrapper.IdentifierProvider;
 | 
				
			||||||
import net.tomatentum.marinara.util.LoggerUtil;
 | 
					import net.tomatentum.marinara.util.LoggerUtil;
 | 
				
			||||||
import net.tomatentum.marinara.wrapper.LibraryWrapper;
 | 
					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 {
 | 
					public class JavacordWrapper extends LibraryWrapper {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private DiscordApi api;
 | 
					 | 
				
			||||||
    private JavacordContextObjectProvider contextObjectProvider;
 | 
					    private JavacordContextObjectProvider contextObjectProvider;
 | 
				
			||||||
 | 
					    private CommandRegisterer<SlashCommandBuilder> commandRegisterer;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
					    private Logger logger = LoggerUtil.getLogger(getClass());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public JavacordWrapper(DiscordApi api) {
 | 
					    public JavacordWrapper(DiscordApi api) {
 | 
				
			||||||
        this.api = api;
 | 
					 | 
				
			||||||
        this.contextObjectProvider = new JavacordContextObjectProvider();
 | 
					        this.contextObjectProvider = new JavacordContextObjectProvider();
 | 
				
			||||||
        if (api != null)
 | 
					        var converter = CommandConverter.of(new JavacordConverterSpec());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (api != null) {
 | 
				
			||||||
 | 
					            this.commandRegisterer = CommandRegisterer.of(new JavacordRegistererStrategy(api), converter);
 | 
				
			||||||
            api.addInteractionCreateListener((e) -> handleInteraction(e.getInteraction()));
 | 
					            api.addInteractionCreateListener((e) -> handleInteraction(e.getInteraction()));
 | 
				
			||||||
        else
 | 
					        }else
 | 
				
			||||||
            logger.warn("DiscordApi was null so no Events were subscribed to.");
 | 
					            logger.warn("DiscordApi was null so no Events were subscribed to.");
 | 
				
			||||||
        logger.info("Javacord wrapper loaded!");
 | 
					        logger.info("Javacord wrapper loaded!");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public InteractionType getInteractionType(Object context) {
 | 
					    public CommandRegisterer<?> getRegisterer() {
 | 
				
			||||||
        if (AutocompleteInteraction.class.isAssignableFrom(context.getClass()))
 | 
					        return this.commandRegisterer;
 | 
				
			||||||
            return InteractionType.AUTOCOMPLETE;
 | 
					 | 
				
			||||||
        if (ApplicationCommandInteraction.class.isAssignableFrom(context.getClass()))
 | 
					 | 
				
			||||||
            return InteractionType.COMMAND;
 | 
					 | 
				
			||||||
        if (ButtonInteraction.class.isAssignableFrom(context.getClass()))
 | 
					 | 
				
			||||||
            return InteractionType.BUTTON;
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void registerSlashCommands(SlashCommandDefinition[] defs) {
 | 
					    public IdentifierProvider createIdentifierProvider() {
 | 
				
			||||||
        HashMap<Long, Set<SlashCommandBuilder>> serverCommands = new HashMap<>();
 | 
					        return IdentifierProvider.of(
 | 
				
			||||||
        Set<SlashCommandBuilder> globalCommands = new HashSet<>();
 | 
					            new SlashCommandIdentifierConverter(),
 | 
				
			||||||
        for (SlashCommandDefinition slashCommandDefinition : defs) {
 | 
					            new AutocompleteIdentifierConverter(),
 | 
				
			||||||
            SlashCommandBuilder builder = convertSlashCommand(slashCommandDefinition);
 | 
					            new ButtonIdentifierConverter()
 | 
				
			||||||
            if (slashCommandDefinition.getFullSlashCommand().serverIds().length > 0) {
 | 
					        );
 | 
				
			||||||
                for (long serverId : slashCommandDefinition.getFullSlashCommand().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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public ExecutableSlashCommandDefinition getCommandDefinition(Object context) {
 | 
					 | 
				
			||||||
        if (!(context instanceof SlashCommandInteraction))
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SlashCommandInteraction interaction = (SlashCommandInteraction) context;
 | 
					 | 
				
			||||||
        ExecutableSlashCommandDefinition.Builder builder = new ExecutableSlashCommandDefinition.Builder();
 | 
					 | 
				
			||||||
        List<SlashCommandInteractionOption> 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);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return builder.build();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private SlashCommandBuilder convertSlashCommand(SlashCommandDefinition def) {
 | 
					 | 
				
			||||||
        List<org.javacord.api.interaction.SlashCommandOption> options = new ArrayList<>();
 | 
					 | 
				
			||||||
        SlashCommand cmd = def.getFullSlashCommand();
 | 
					 | 
				
			||||||
        if (!def.isRootCommand()) {
 | 
					 | 
				
			||||||
            Arrays.stream(def.getSubCommands(null)).map(this::convertSubCommandDef).forEach(options::add);
 | 
					 | 
				
			||||||
            Arrays.stream(def.getSubCommandGroups()).map((x) -> convertSubCommandGroupDef(def, x)).forEach(options::add);
 | 
					 | 
				
			||||||
        }else {
 | 
					 | 
				
			||||||
            Arrays.stream(cmd.options()).map(this::convertOptionDef).forEach(options::add);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return 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());
 | 
					 | 
				
			||||||
        List<org.javacord.api.interaction.SlashCommandOption> 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(SubCommand sub) {
 | 
					 | 
				
			||||||
        List<org.javacord.api.interaction.SlashCommandOption> 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<org.javacord.api.interaction.SlashCommandOptionChoice> convertChoices(SlashCommandOption option) {
 | 
					 | 
				
			||||||
        List<org.javacord.api.interaction.SlashCommandOptionChoice> convertedChoices = new ArrayList<>();
 | 
					 | 
				
			||||||
        for (SlashCommandOptionChoice choice : ExecutableSlashCommandDefinition.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());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return convertedChoices;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String getButtonId(Object context) {
 | 
					 | 
				
			||||||
        ButtonInteraction button = (ButtonInteraction) context;
 | 
					 | 
				
			||||||
        return button.getCustomId();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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<AutocompleteInteraction> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public InteractionIdentifier convert(AutocompleteInteraction context) {
 | 
				
			||||||
 | 
					        List<SlashCommandInteractionOption> options = context.getOptions();
 | 
				
			||||||
 | 
					        String commandName = context.getCommandName();
 | 
				
			||||||
 | 
					        if (!options.isEmpty()) {
 | 
				
			||||||
 | 
					            List<SlashCommandInteractionOption> 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); 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<ButtonInteraction> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public InteractionIdentifier convert(ButtonInteraction context) {
 | 
				
			||||||
 | 
					        return InteractionIdentifier.builder().name(context.getCustomId()).type(InteractionType.BUTTON).build();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<SlashCommandInteraction> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public InteractionIdentifier convert(SlashCommandInteraction context) {
 | 
				
			||||||
 | 
					        List<SlashCommandInteractionOption> options = context.getOptions();
 | 
				
			||||||
 | 
					        String commandName = context.getCommandName();
 | 
				
			||||||
 | 
					        if (!options.isEmpty()) {
 | 
				
			||||||
 | 
					            List<SlashCommandInteractionOption> 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); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
package net.tomatentum.marinara.test.javacord;
 | 
					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<String> {
 | 
					public enum TestChoiceEnum implements ChoiceValueProvider<String> {
 | 
				
			||||||
    TestValue("testValue"),
 | 
					    TestValue("testValue"),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user