Compare commits
25 Commits
56b668851b
...
dev
Author | SHA1 | Date | |
---|---|---|---|
a3c5eb62ac | |||
996f854ff7
|
|||
d2eec8b07c
|
|||
caa2ee7089
|
|||
2e5979e6e4 | |||
ab1eb74e85
|
|||
a5737b9eaa
|
|||
faca21724c
|
|||
4c5e28b679
|
|||
33f355e6ea | |||
d32ac62b4a
|
|||
e7c35d9308
|
|||
d4a91f3251
|
|||
bce4ce7812
|
|||
bae077654e
|
|||
203498de68
|
|||
24df1731da
|
|||
e3fc10a1ce
|
|||
78cacb7eb6
|
|||
7287d44645
|
|||
630c8ddee5
|
|||
4e27e6ce56
|
|||
432cf78a2e
|
|||
f940f48566
|
|||
f4ee258eb1
|
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[versions]
|
[versions]
|
||||||
junit-jupiter = "5.10.2"
|
junit-jupiter = "5.10.2"
|
||||||
log4j = "2.24.1"
|
slf4j = "2.0.17"
|
||||||
javacord = "3.8.0"
|
javacord = "3.8.0"
|
||||||
discord4j = "3.2.7"
|
discord4j = "3.2.7"
|
||||||
geantyref = "2.0.0"
|
geantyref = "2.0.0"
|
||||||
@@ -11,7 +11,7 @@ mockito = "5.15.2"
|
|||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
|
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
|
||||||
log4j = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j"}
|
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j"}
|
||||||
javacord = { module = "org.javacord:javacord", version.ref = "javacord"}
|
javacord = { module = "org.javacord:javacord", version.ref = "javacord"}
|
||||||
discord4j = { module = "com.discord4j:discord4j-core", version.ref = "discord4j"}
|
discord4j = { module = "com.discord4j:discord4j-core", version.ref = "discord4j"}
|
||||||
geantyref = { module = "io.leangen.geantyref:geantyref", version.ref = "geantyref"}
|
geantyref = { module = "io.leangen.geantyref:geantyref", version.ref = "geantyref"}
|
||||||
|
@@ -20,7 +20,7 @@ dependencies {
|
|||||||
testImplementation(libs.junit.jupiter)
|
testImplementation(libs.junit.jupiter)
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
implementation(libs.log4j)
|
implementation(libs.slf4j)
|
||||||
implementation(libs.geantyref)
|
implementation(libs.geantyref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
package net.tomatentum.marinara;
|
package net.tomatentum.marinara;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import net.tomatentum.marinara.registry.InteractionCheckRegistry;
|
import net.tomatentum.marinara.registry.InteractionCheckRegistry;
|
||||||
import net.tomatentum.marinara.registry.InteractionRegistry;
|
import net.tomatentum.marinara.registry.InteractionRegistry;
|
||||||
|
@@ -5,7 +5,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import net.tomatentum.marinara.util.LoggerUtil;
|
import net.tomatentum.marinara.util.LoggerUtil;
|
||||||
import net.tomatentum.marinara.util.ReflectionUtil;
|
import net.tomatentum.marinara.util.ReflectionUtil;
|
||||||
@@ -27,7 +27,7 @@ public record AppliedCheck(InteractionCheck<?> check, Annotation annotation) {
|
|||||||
logger.debug("Pre Check {} {} with context {}", check.getClass().getName(), result ? "succeeded" : "failed", context.toString());
|
logger.debug("Pre Check {} {} with context {}", check.getClass().getName(), result ? "succeeded" : "failed", context.toString());
|
||||||
return result;
|
return result;
|
||||||
} catch (IllegalAccessException | InvocationTargetException | SecurityException e) {
|
} catch (IllegalAccessException | InvocationTargetException | SecurityException e) {
|
||||||
logger.fatal(e);
|
logger.error("Failed executing pre-check", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ public record AppliedCheck(InteractionCheck<?> check, Annotation annotation) {
|
|||||||
logger.debug("Executing post check {} with context {}", check.getClass().getName(), context.toString());
|
logger.debug("Executing post check {} with context {}", check.getClass().getName(), context.toString());
|
||||||
method.invoke(check, context, annotation);
|
method.invoke(check, context, annotation);
|
||||||
} catch (IllegalAccessException | InvocationTargetException | SecurityException e) {
|
} catch (IllegalAccessException | InvocationTargetException | SecurityException e) {
|
||||||
logger.fatal(e);
|
logger.error("Failed executing post-check", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,8 +4,9 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import net.tomatentum.marinara.interaction.commands.annotation.CommandChoices;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption.PlaceHolderEnum;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption.PlaceHolderEnum;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
||||||
@@ -18,10 +19,11 @@ import net.tomatentum.marinara.util.LoggerUtil;
|
|||||||
public class SlashCommandDefinition {
|
public class SlashCommandDefinition {
|
||||||
|
|
||||||
public static SlashCommandOptionChoice[] getActualChoices(SlashCommandOption option) {
|
public static SlashCommandOptionChoice[] getActualChoices(SlashCommandOption option) {
|
||||||
SlashCommandOptionChoice[] choices = option.choices();
|
CommandChoices choices = option.choices();
|
||||||
if (choices.length <= 0 && !option.choiceEnum().equals(PlaceHolderEnum.class))
|
SlashCommandOptionChoice[] actualChoices = choices.value();
|
||||||
choices = EnumChoices.of(option.choiceEnum()).choices();
|
if (choices.value().length <= 0 && !choices.cenum().equals(PlaceHolderEnum.class))
|
||||||
return choices;
|
actualChoices = EnumChoices.of(choices.cenum()).choices();
|
||||||
|
return actualChoices;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<InteractionIdentifier> entries;
|
private Set<InteractionIdentifier> entries;
|
||||||
@@ -66,13 +68,13 @@ public class SlashCommandDefinition {
|
|||||||
.map(x -> x.parent())
|
.map(x -> x.parent())
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return InteractionIdentifier.distinct(subCommandGroups).toArray(SlashCommandIdentifier[]::new);
|
return subCommandGroups.toArray(SlashCommandIdentifier[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlashCommandIdentifier[] getSubCommands() {
|
public SlashCommandIdentifier[] getSubCommands() {
|
||||||
if (isRootCommand)
|
if (isRootCommand)
|
||||||
return null;
|
return null;
|
||||||
return InteractionIdentifier.distinct(entries.stream().filter(x -> x instanceof RootCommandIdentifier).toList()).toArray(SlashCommandIdentifier[]::new);
|
return entries.stream().filter(x -> x.parent() instanceof RootCommandIdentifier).toArray(SlashCommandIdentifier[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlashCommandIdentifier[] getSubCommands(String groupName) {
|
public SlashCommandIdentifier[] getSubCommands(String groupName) {
|
||||||
@@ -84,7 +86,7 @@ public class SlashCommandDefinition {
|
|||||||
.map(x -> x.parent().parent())
|
.map(x -> x.parent().parent())
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return InteractionIdentifier.distinct(subCommands).toArray(SlashCommandIdentifier[]::new);
|
return subCommands.toArray(SlashCommandIdentifier[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -95,6 +97,10 @@ public class SlashCommandDefinition {
|
|||||||
return this.rootIdentifier().equals(other.rootIdentifier());
|
return this.rootIdentifier().equals(other.rootIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long[] serverIds() {
|
||||||
|
return rootIdentifier().serverIds();
|
||||||
|
}
|
||||||
|
|
||||||
public Set<InteractionIdentifier> entries() {
|
public Set<InteractionIdentifier> entries() {
|
||||||
return this.entries;
|
return this.entries;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,8 @@
|
|||||||
|
package net.tomatentum.marinara.interaction.commands.annotation;
|
||||||
|
|
||||||
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption.PlaceHolderEnum;
|
||||||
|
|
||||||
|
public @interface CommandChoices {
|
||||||
|
public SlashCommandOptionChoice[] value() default {};
|
||||||
|
public Class<? extends Enum<?>> cenum() default PlaceHolderEnum.class;
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
package net.tomatentum.marinara.interaction.commands.annotation;
|
||||||
|
|
||||||
|
public @interface Range {
|
||||||
|
public double min() default Double.MIN_VALUE;
|
||||||
|
public double max() default Double.MAX_VALUE;
|
||||||
|
}
|
@@ -15,8 +15,8 @@ public @interface SlashCommandOption {
|
|||||||
public SlashCommandOptionType type() default SlashCommandOptionType.STRING;
|
public SlashCommandOptionType type() default SlashCommandOptionType.STRING;
|
||||||
public boolean required() default false;
|
public boolean required() default false;
|
||||||
public boolean autocomplete() default false;
|
public boolean autocomplete() default false;
|
||||||
public SlashCommandOptionChoice[] choices() default {};
|
public Range range() default @Range;
|
||||||
public Class<? extends Enum<?>> choiceEnum() default PlaceHolderEnum.class;
|
public CommandChoices choices() default @CommandChoices;
|
||||||
|
|
||||||
public static enum PlaceHolderEnum {
|
public static enum PlaceHolderEnum {
|
||||||
|
|
||||||
|
@@ -1,8 +1,5 @@
|
|||||||
package net.tomatentum.marinara.interaction.ident;
|
package net.tomatentum.marinara.interaction.ident;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import net.tomatentum.marinara.interaction.InteractionType;
|
import net.tomatentum.marinara.interaction.InteractionType;
|
||||||
@@ -38,20 +35,6 @@ public class InteractionIdentifier {
|
|||||||
tryAddDescriptions(receiver.parent(), provider.parent());
|
tryAddDescriptions(receiver.parent(), provider.parent());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: Might not be the best solution. Propagating to future
|
|
||||||
* returns only one Identifier per name and takes the first present description
|
|
||||||
*/
|
|
||||||
public static Collection<InteractionIdentifier> distinct(List<InteractionIdentifier> identifiers) {
|
|
||||||
HashMap<String, InteractionIdentifier> distinctIdentifiers = new HashMap<>();
|
|
||||||
identifiers.forEach((x) -> {
|
|
||||||
InteractionIdentifier current = distinctIdentifiers.get(x.name());
|
|
||||||
if (current == null || (current.description().isBlank() && !x.description().isBlank()))
|
|
||||||
distinctIdentifiers.put(x.name(), x);
|
|
||||||
});
|
|
||||||
return distinctIdentifiers.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
private InteractionIdentifier parent;
|
private InteractionIdentifier parent;
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package net.tomatentum.marinara.interaction.ident;
|
package net.tomatentum.marinara.interaction.ident;
|
||||||
|
|
||||||
|
import net.tomatentum.marinara.interaction.InteractionType;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
||||||
|
|
||||||
public class RootCommandIdentifier extends SlashCommandIdentifier {
|
public class RootCommandIdentifier extends SlashCommandIdentifier {
|
||||||
@@ -10,10 +11,10 @@ public class RootCommandIdentifier extends SlashCommandIdentifier {
|
|||||||
InteractionIdentifier parent,
|
InteractionIdentifier parent,
|
||||||
String name,
|
String name,
|
||||||
String description,
|
String description,
|
||||||
|
InteractionType type,
|
||||||
SlashCommandOption[] options,
|
SlashCommandOption[] options,
|
||||||
boolean isAutocomplete,
|
|
||||||
long[] serverIds) {
|
long[] serverIds) {
|
||||||
super(parent, name, description, options, isAutocomplete);
|
super(parent, name, description, type, options);
|
||||||
this.serverIds = serverIds;
|
this.serverIds = serverIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +27,6 @@ public class RootCommandIdentifier extends SlashCommandIdentifier {
|
|||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
private SlashCommandOption[] options;
|
private SlashCommandOption[] options;
|
||||||
private boolean isAutocomplete = false;
|
|
||||||
private long[] serverIds;
|
private long[] serverIds;
|
||||||
|
|
||||||
|
|
||||||
@@ -66,15 +66,6 @@ public class RootCommandIdentifier extends SlashCommandIdentifier {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean autocomplete() {
|
|
||||||
return this.isAutocomplete;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder autocomplete(boolean isAutocomplete) {
|
|
||||||
this.isAutocomplete = isAutocomplete;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long[] serverIds() {
|
public long[] serverIds() {
|
||||||
return this.serverIds;
|
return this.serverIds;
|
||||||
}
|
}
|
||||||
@@ -84,8 +75,14 @@ public class RootCommandIdentifier extends SlashCommandIdentifier {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlashCommandIdentifier build() {
|
public SlashCommandIdentifier build(boolean autocomplete) {
|
||||||
return new RootCommandIdentifier(parent, name, description, options, isAutocomplete, serverIds);
|
return new RootCommandIdentifier(
|
||||||
|
parent,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND,
|
||||||
|
options,
|
||||||
|
serverIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -11,10 +11,10 @@ public class SlashCommandIdentifier extends InteractionIdentifier {
|
|||||||
InteractionIdentifier parent,
|
InteractionIdentifier parent,
|
||||||
String name,
|
String name,
|
||||||
String description,
|
String description,
|
||||||
SlashCommandOption[] options,
|
InteractionType type,
|
||||||
boolean isAutocomplete
|
SlashCommandOption[] options
|
||||||
) {
|
) {
|
||||||
super(parent, name, description, isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND);
|
super(parent, name, description, type);
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +27,6 @@ public class SlashCommandIdentifier extends InteractionIdentifier {
|
|||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
private SlashCommandOption[] options;
|
private SlashCommandOption[] options;
|
||||||
private boolean isAutocomplete = false;
|
|
||||||
|
|
||||||
public InteractionIdentifier parent() {
|
public InteractionIdentifier parent() {
|
||||||
return parent;
|
return parent;
|
||||||
@@ -65,17 +64,13 @@ public class SlashCommandIdentifier extends InteractionIdentifier {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean autocomplete() {
|
public SlashCommandIdentifier build(boolean autocomplete) {
|
||||||
return this.isAutocomplete;
|
return new SlashCommandIdentifier(
|
||||||
}
|
parent,
|
||||||
|
name,
|
||||||
public Builder autocomplete(boolean isAutocomplete) {
|
description,
|
||||||
this.isAutocomplete = isAutocomplete;
|
autocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND,
|
||||||
return this;
|
options);
|
||||||
}
|
|
||||||
|
|
||||||
public SlashCommandIdentifier build() {
|
|
||||||
return new SlashCommandIdentifier(parent, name, description, options, isAutocomplete);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ public class AutoCompleteInteractionMethod extends InteractionMethod {
|
|||||||
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
|
||||||
|
@@ -7,7 +7,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import net.tomatentum.marinara.Marinara;
|
import net.tomatentum.marinara.Marinara;
|
||||||
import net.tomatentum.marinara.checks.AppliedCheck;
|
import net.tomatentum.marinara.checks.AppliedCheck;
|
||||||
@@ -69,7 +69,7 @@ public abstract class InteractionMethod {
|
|||||||
try {
|
try {
|
||||||
method.invoke(handler, getParameters(context));
|
method.invoke(handler, getParameters(context));
|
||||||
}catch (IllegalAccessException | InvocationTargetException ex) {
|
}catch (IllegalAccessException | InvocationTargetException ex) {
|
||||||
logger.fatal(ex);
|
logger.error("InteractionMethod failed to run", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.appliedChecks.forEach(x -> x.post(context));
|
this.appliedChecks.forEach(x -> x.post(context));
|
||||||
|
@@ -3,7 +3,7 @@ package net.tomatentum.marinara.parser;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import net.tomatentum.marinara.interaction.annotation.Button;
|
import net.tomatentum.marinara.interaction.annotation.Button;
|
||||||
import net.tomatentum.marinara.util.LoggerUtil;
|
import net.tomatentum.marinara.util.LoggerUtil;
|
||||||
|
@@ -6,7 +6,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import net.tomatentum.marinara.checks.AppliedCheck;
|
import net.tomatentum.marinara.checks.AppliedCheck;
|
||||||
import net.tomatentum.marinara.checks.InteractionCheck;
|
import net.tomatentum.marinara.checks.InteractionCheck;
|
||||||
|
@@ -3,7 +3,7 @@ package net.tomatentum.marinara.parser;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import net.tomatentum.marinara.interaction.InteractionType;
|
import net.tomatentum.marinara.interaction.InteractionType;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
||||||
@@ -37,9 +37,8 @@ public class SlashCommandParser implements AnnotationParser {
|
|||||||
.name(cmd.name())
|
.name(cmd.name())
|
||||||
.description(cmd.description())
|
.description(cmd.description())
|
||||||
.options(cmd.options())
|
.options(cmd.options())
|
||||||
.autocomplete(isAutoComplete)
|
|
||||||
.serverIds(cmd.serverIds())
|
.serverIds(cmd.serverIds())
|
||||||
.build();
|
.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);
|
||||||
@@ -57,11 +56,10 @@ public class SlashCommandParser implements AnnotationParser {
|
|||||||
.name(subCmd.name())
|
.name(subCmd.name())
|
||||||
.description(subCmd.description())
|
.description(subCmd.description())
|
||||||
.options(subCmd.options())
|
.options(subCmd.options())
|
||||||
.autocomplete(isAutoComplete)
|
.build(isAutoComplete);
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.trace("Parsed using SlashCommandParser for method {} with the result:\n{}", ReflectionUtil.getFullMethodName(method), lastIdentifier.toString());
|
logger.trace("Parsed using SlashCommandParser for method {} with the result: {}", ReflectionUtil.getFullMethodName(method), lastIdentifier.toString());
|
||||||
consumer.accept((SlashCommandIdentifier) lastIdentifier);
|
consumer.accept((SlashCommandIdentifier) lastIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import io.leangen.geantyref.GenericTypeReflector;
|
import io.leangen.geantyref.GenericTypeReflector;
|
||||||
import net.tomatentum.marinara.checks.InteractionCheck;
|
import net.tomatentum.marinara.checks.InteractionCheck;
|
||||||
|
@@ -3,7 +3,7 @@ package net.tomatentum.marinara.registry;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import net.tomatentum.marinara.interaction.InteractionType;
|
import net.tomatentum.marinara.interaction.InteractionType;
|
||||||
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
||||||
|
@@ -1,32 +1,35 @@
|
|||||||
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.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
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.commands.SlashCommandDefinition;
|
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
|
||||||
|
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
||||||
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
|
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
|
||||||
import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
|
|
||||||
import net.tomatentum.marinara.util.LoggerUtil;
|
import net.tomatentum.marinara.util.LoggerUtil;
|
||||||
import net.tomatentum.marinara.wrapper.LibraryWrapper;
|
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 Set<InteractionEntry> interactions;
|
private Set<InteractionEntry> interactions;
|
||||||
private Marinara marinara;
|
private Marinara marinara;
|
||||||
|
private IdentifierProvider identifierProvider;
|
||||||
|
|
||||||
public InteractionRegistry(Marinara marinara) {
|
public InteractionRegistry(Marinara marinara) {
|
||||||
this.interactions = new HashSet<>();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,11 +40,12 @@ public class InteractionRegistry {
|
|||||||
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) {
|
||||||
Optional<InteractionEntry> entry = this.interactions.stream().filter(iMethod::equals).findFirst();
|
Optional<InteractionEntry> oentry = this.interactions.stream()
|
||||||
if (entry.isEmpty()) {
|
.filter(i -> i.identifier().equals(iMethod.identifier()))
|
||||||
interactions.add(new InteractionEntry(iMethod.identifier()).addMethod(iMethod));
|
.findFirst();
|
||||||
}else
|
|
||||||
entry.get().addMethod(iMethod);
|
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.debug("Added {} method from {}", iMethod.method().getName(), interactionHandler.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,34 +53,25 @@ public class InteractionRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void registerCommands() {
|
public void registerCommands() {
|
||||||
List<SlashCommandDefinition> defs = new ArrayList<>();
|
List<InteractionIdentifier> slashIdentifiers = interactions.stream()
|
||||||
List<SlashCommandIdentifier> slashIdentifiers = interactions.stream()
|
|
||||||
.filter((x) -> x.type().equals(InteractionType.COMMAND))
|
.filter((x) -> x.type().equals(InteractionType.COMMAND))
|
||||||
.map((x) -> (SlashCommandIdentifier)x.identifier())
|
.map((x) -> x.identifier())
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
slashIdentifiers.forEach((ident) -> {
|
SlashCommandDefinition[] defs = new ObjectAggregator<InteractionIdentifier, RootCommandIdentifier, SlashCommandDefinition>(
|
||||||
Optional<SlashCommandDefinition> appDef = defs.stream()
|
i -> Arrays.asList((RootCommandIdentifier)i.rootNode()),
|
||||||
.filter((x) -> x.rootIdentifier().equals(ident.rootNode()))
|
SlashCommandDefinition::addIdentifier,
|
||||||
.findFirst();
|
SlashCommandDefinition::new)
|
||||||
|
.aggregate(slashIdentifiers)
|
||||||
|
.toArray(SlashCommandDefinition[]::new);
|
||||||
|
|
||||||
if (appDef.isPresent())
|
marinara.getWrapper().getRegisterer().register(defs);
|
||||||
appDef.get().addIdentifier(ident);
|
|
||||||
else
|
|
||||||
defs.add(
|
|
||||||
new SlashCommandDefinition((RootCommandIdentifier) ident.rootNode())
|
|
||||||
.addIdentifier(ident));
|
|
||||||
});
|
|
||||||
|
|
||||||
marinara.getWrapper().registerSlashCommands(defs.toArray(SlashCommandDefinition[]::new));
|
|
||||||
logger.info("Registered all SlashCommands");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(Object context) {
|
public void handle(Object context) {
|
||||||
logger.debug("Received {} interaction ", context);
|
logger.debug("Received {} interaction ", context);
|
||||||
LibraryWrapper wrapper = marinara.getWrapper();
|
|
||||||
interactions.forEach((e) -> {
|
interactions.forEach((e) -> {
|
||||||
if (wrapper.getInteractionIdentifier(context).equals(e.identifier())) {
|
if (this.identifierProvider.provide(context).equals(e.identifier())) {
|
||||||
logger.info("Running {} interaction using {}\ncontext: {}", e.type(), e.toString(), context.toString());
|
logger.info("Running {} interaction using {}\ncontext: {}", e.type(), e.toString(), context.toString());
|
||||||
e.runAll(context);
|
e.runAll(context);
|
||||||
}
|
}
|
||||||
|
@@ -1,21 +1,14 @@
|
|||||||
package net.tomatentum.marinara.util;
|
package net.tomatentum.marinara.util;
|
||||||
|
|
||||||
import java.util.Properties;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.apache.logging.log4j.Level;
|
import org.slf4j.helpers.NOPLoggerFactory;
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.logging.log4j.simple.SimpleLogger;
|
|
||||||
import org.apache.logging.log4j.util.PropertiesUtil;
|
|
||||||
import org.apache.logging.log4j.util.ProviderUtil;
|
|
||||||
|
|
||||||
public class LoggerUtil {
|
public class LoggerUtil {
|
||||||
public static Logger getLogger(String name) {
|
public static Logger getLogger(String name) {
|
||||||
if (ProviderUtil.hasProviders()) {
|
if (LoggerFactory.getILoggerFactory() instanceof NOPLoggerFactory)
|
||||||
return LogManager.getLogger(name);
|
return new SimpleLogger(name);
|
||||||
}else
|
return LoggerFactory.getLogger(name);
|
||||||
return new SimpleLogger(name, Level.DEBUG, true, false, true, true, "yyyy-MM-dd HH:mm:ss.SSSZ", null,
|
|
||||||
new PropertiesUtil(new Properties()), System.out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Logger getLogger(Class<?> clazz) {
|
public static Logger getLogger(Class<?> clazz) {
|
||||||
|
@@ -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<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -102,6 +102,6 @@ public final class ReflectionUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getFullMethodName(Method method) {
|
public static String getFullMethodName(Method method) {
|
||||||
return method.getClass().getName() + "." + method.getName();
|
return method.getDeclaringClass().getName() + "." + method.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,55 @@
|
|||||||
|
package net.tomatentum.marinara.util;
|
||||||
|
|
||||||
|
import org.slf4j.Marker;
|
||||||
|
import org.slf4j.event.Level;
|
||||||
|
import org.slf4j.helpers.LegacyAbstractLogger;
|
||||||
|
import org.slf4j.helpers.MessageFormatter;
|
||||||
|
|
||||||
|
public class SimpleLogger extends LegacyAbstractLogger {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public SimpleLogger(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTraceEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDebugEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInfoEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWarnEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isErrorEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFullyQualifiedCallerName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments,
|
||||||
|
Throwable throwable) {
|
||||||
|
String formatted = MessageFormatter.basicArrayFormat(messagePattern, arguments);
|
||||||
|
System.out.println("[%s] %s => %s".formatted(level, this.name, formatted));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,14 +1,18 @@
|
|||||||
package net.tomatentum.marinara.interaction.commands;
|
package net.tomatentum.marinara.wrapper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
||||||
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
||||||
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
|
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
|
||||||
import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
|
import net.tomatentum.marinara.interaction.ident.SlashCommandIdentifier;
|
||||||
|
import net.tomatentum.marinara.util.LoggerUtil;
|
||||||
|
|
||||||
public class CommandConverter<A extends Object, O extends Object, C extends Object> {
|
public class CommandConverter<A extends Object, O extends Object, C extends Object> {
|
||||||
|
|
||||||
@@ -16,6 +20,8 @@ public class CommandConverter<A extends Object, O extends Object, C extends Obje
|
|||||||
return new CommandConverter<>(spec);
|
return new CommandConverter<>(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Logger logger = LoggerUtil.getLogger(getClass());
|
||||||
|
|
||||||
private Spec<A, O, C> spec;
|
private Spec<A, O, C> spec;
|
||||||
|
|
||||||
CommandConverter(Spec<A, O, C> spec) {
|
CommandConverter(Spec<A, O, C> spec) {
|
||||||
@@ -23,6 +29,7 @@ public class CommandConverter<A extends Object, O extends Object, C extends Obje
|
|||||||
}
|
}
|
||||||
|
|
||||||
public A convert(SlashCommandDefinition def) {
|
public A convert(SlashCommandDefinition def) {
|
||||||
|
logger.debug("Converting command {}", def);
|
||||||
List<O> options = new ArrayList<>();
|
List<O> options = new ArrayList<>();
|
||||||
if (!def.isRootCommand()) {
|
if (!def.isRootCommand()) {
|
||||||
Arrays.stream(def.getSubCommands()).map(this::convertSubCommand).forEach(options::add);
|
Arrays.stream(def.getSubCommands()).map(this::convertSubCommand).forEach(options::add);
|
||||||
@@ -34,17 +41,20 @@ public class CommandConverter<A extends Object, O extends Object, C extends Obje
|
|||||||
}
|
}
|
||||||
|
|
||||||
private O convertSubCommandGroup(SlashCommandDefinition def, InteractionIdentifier identifier) {
|
private O convertSubCommandGroup(SlashCommandDefinition def, InteractionIdentifier identifier) {
|
||||||
|
logger.debug("Converting subCommandGroup {} of {}", identifier, def);
|
||||||
SlashCommandIdentifier[] subCommands = def.getSubCommands(identifier.name());
|
SlashCommandIdentifier[] subCommands = def.getSubCommands(identifier.name());
|
||||||
List<O> convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommand).toList();
|
List<O> convertedSubCommands = Arrays.stream(subCommands).map(this::convertSubCommand).toList();
|
||||||
return spec.convertSubCommandGroup(identifier, convertedSubCommands);
|
return spec.convertSubCommandGroup(identifier, convertedSubCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
private O convertSubCommand(SlashCommandIdentifier identifier) {
|
private O convertSubCommand(SlashCommandIdentifier identifier) {
|
||||||
|
logger.debug("Converting subCommand {}", identifier);
|
||||||
List<O> options = Arrays.stream(identifier.options()).map(this::convertOption).toList();
|
List<O> options = Arrays.stream(identifier.options()).map(this::convertOption).toList();
|
||||||
return spec.convertSubCommand(identifier, options);
|
return spec.convertSubCommand(identifier, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private O convertOption(SlashCommandOption option) {
|
private O convertOption(SlashCommandOption option) {
|
||||||
|
logger.debug("Converting option {}", option);
|
||||||
List<C> choices = Arrays.stream(SlashCommandDefinition.getActualChoices(option)).map(spec::convertChoice).toList();
|
List<C> choices = Arrays.stream(SlashCommandDefinition.getActualChoices(option)).map(spec::convertChoice).toList();
|
||||||
return spec.convertOption(option, choices);
|
return spec.convertOption(option, choices);
|
||||||
}
|
}
|
@@ -0,0 +1,51 @@
|
|||||||
|
package net.tomatentum.marinara.wrapper;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
|
||||||
|
import net.tomatentum.marinara.util.LoggerUtil;
|
||||||
|
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 Logger logger = LoggerUtil.getLogger(getClass());
|
||||||
|
|
||||||
|
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);
|
||||||
|
logger.info("Registered all SlashCommands");
|
||||||
|
}
|
||||||
|
|
||||||
|
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.slf4j.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,16 +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.ident.InteractionIdentifier;
|
|
||||||
|
|
||||||
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) {
|
||||||
@@ -26,9 +22,8 @@ public abstract class LibraryWrapper {
|
|||||||
interactionSubscriber.remove(consumer);
|
interactionSubscriber.remove(consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void registerSlashCommands(SlashCommandDefinition[] defs);
|
public abstract CommandRegisterer<?> getRegisterer();
|
||||||
public abstract InteractionIdentifier getInteractionIdentifier(Object context);
|
public abstract IdentifierProvider createIdentifierProvider();
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
@@ -19,11 +19,12 @@ dependencies {
|
|||||||
// Use JUnit Jupiter for testing.
|
// Use JUnit Jupiter for testing.
|
||||||
testImplementation(libs.junit.jupiter)
|
testImplementation(libs.junit.jupiter)
|
||||||
testImplementation(libs.mockito)
|
testImplementation(libs.mockito)
|
||||||
|
testImplementation(libs.discord4j)
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
implementation(libs.log4j)
|
implementation(libs.slf4j)
|
||||||
implementation(libs.discord4j) {
|
implementation(libs.discord4j) {
|
||||||
// exclude(module="discord4j-voice")
|
exclude(module="discord4j-voice")
|
||||||
}
|
}
|
||||||
implementation(libs.geantyref)
|
implementation(libs.geantyref)
|
||||||
implementation(project(":lib"))
|
implementation(project(":lib"))
|
||||||
|
@@ -6,11 +6,11 @@ import discord4j.core.object.command.ApplicationCommandOption.Type;
|
|||||||
import discord4j.discordjson.json.ApplicationCommandOptionChoiceData;
|
import discord4j.discordjson.json.ApplicationCommandOptionChoiceData;
|
||||||
import discord4j.discordjson.json.ApplicationCommandOptionData;
|
import discord4j.discordjson.json.ApplicationCommandOptionData;
|
||||||
import discord4j.discordjson.json.ApplicationCommandRequest;
|
import discord4j.discordjson.json.ApplicationCommandRequest;
|
||||||
import net.tomatentum.marinara.interaction.commands.CommandConverter;
|
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
||||||
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
||||||
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
|
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
|
||||||
|
import net.tomatentum.marinara.wrapper.CommandConverter;
|
||||||
|
|
||||||
public class Discord4JConverterSpec implements CommandConverter.Spec<ApplicationCommandRequest, ApplicationCommandOptionData, ApplicationCommandOptionChoiceData> {
|
public class Discord4JConverterSpec implements CommandConverter.Spec<ApplicationCommandRequest, ApplicationCommandOptionData, ApplicationCommandOptionChoiceData> {
|
||||||
|
|
||||||
@@ -56,6 +56,10 @@ public class Discord4JConverterSpec implements CommandConverter.Spec<Application
|
|||||||
.description(option.description())
|
.description(option.description())
|
||||||
.required(option.required())
|
.required(option.required())
|
||||||
.autocomplete(option.autocomplete())
|
.autocomplete(option.autocomplete())
|
||||||
|
.minLength(Double.valueOf(option.range().min()).intValue())
|
||||||
|
.minValue(option.range().min())
|
||||||
|
.maxLength(Double.valueOf(option.range().max()).intValue())
|
||||||
|
.maxValue(option.range().max())
|
||||||
.choices(choices)
|
.choices(choices)
|
||||||
.build();
|
.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,30 +1,25 @@
|
|||||||
package net.tomatentum.marinara.wrapper.discord4j;
|
package net.tomatentum.marinara.wrapper.discord4j;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.slf4j.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 net.tomatentum.marinara.interaction.InteractionType;
|
|
||||||
import net.tomatentum.marinara.interaction.commands.CommandConverter;
|
|
||||||
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
|
|
||||||
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
|
||||||
import net.tomatentum.marinara.util.LoggerUtil;
|
import net.tomatentum.marinara.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 {
|
||||||
|
|
||||||
@@ -38,93 +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 CommandConverter<ApplicationCommandRequest, ApplicationCommandOptionData, ApplicationCommandOptionChoiceData> commandConverter;
|
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();
|
||||||
this.commandConverter = CommandConverter.of(new Discord4JConverterSpec());
|
var converter = CommandConverter.of(new Discord4JConverterSpec());
|
||||||
|
|
||||||
if (api != null)
|
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 void registerSlashCommands(SlashCommandDefinition[] defs) {
|
public CommandRegisterer<?> getRegisterer() {
|
||||||
HashMap<Long, List<ApplicationCommandRequest>> serverCommands = new HashMap<>();
|
return this.commandRegisterer;
|
||||||
List<ApplicationCommandRequest> globalCommands = new ArrayList<>();
|
|
||||||
long applicationId = api.getRestClient().getApplicationId().block();
|
|
||||||
|
|
||||||
for (SlashCommandDefinition slashCommandDefinition : defs) {
|
|
||||||
ApplicationCommandRequest request = this.commandConverter.convert(slashCommandDefinition);
|
|
||||||
if (slashCommandDefinition.rootIdentifier().serverIds().length > 0) {
|
|
||||||
for (long serverId : slashCommandDefinition.rootIdentifier().serverIds()) {
|
|
||||||
serverCommands.putIfAbsent(serverId, new ArrayList<>());
|
|
||||||
serverCommands.get(serverId).add(request);
|
|
||||||
}
|
|
||||||
}else
|
|
||||||
globalCommands.add(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (long serverId : serverCommands.keySet()) {
|
|
||||||
api.getRestClient().getApplicationService().bulkOverwriteGuildApplicationCommand(applicationId, serverId, serverCommands.get(serverId));
|
|
||||||
}
|
|
||||||
api.getRestClient().getApplicationService().bulkOverwriteGlobalApplicationCommand(applicationId, globalCommands);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InteractionIdentifier getInteractionIdentifier(Object context) {
|
public IdentifierProvider createIdentifierProvider() {
|
||||||
|
return IdentifierProvider.of(
|
||||||
if (context instanceof ButtonInteractionEvent) {
|
new SlashCommandIdentifierConverter(),
|
||||||
ButtonInteractionEvent interaction = (ButtonInteractionEvent) context;
|
new AutocompleteIdentifierConverter(),
|
||||||
return InteractionIdentifier.builder().name(interaction.getCustomId()).type(InteractionType.BUTTON).build();
|
new ButtonIdentifierConverter()
|
||||||
}
|
);
|
||||||
|
|
||||||
List<ApplicationCommandInteractionOption> options;
|
|
||||||
String commandName;
|
|
||||||
boolean isAutocomplete = false;
|
|
||||||
|
|
||||||
if (context instanceof ChatInputInteractionEvent) {
|
|
||||||
ChatInputInteractionEvent interaction = (ChatInputInteractionEvent) context;
|
|
||||||
options = SUB_FILTER.apply(interaction.getOptions());
|
|
||||||
commandName = interaction.getCommandName();
|
|
||||||
}else if (context instanceof ChatInputAutoCompleteEvent) {
|
|
||||||
ChatInputAutoCompleteEvent interaction = (ChatInputAutoCompleteEvent) context;
|
|
||||||
options = SUB_FILTER.apply(interaction.getOptions());
|
|
||||||
commandName = interaction.getCommandName();
|
|
||||||
isAutocomplete = true;
|
|
||||||
}else
|
|
||||||
return null;
|
|
||||||
|
|
||||||
InteractionIdentifier last = InteractionIdentifier.slashBuilder().name(commandName).autocomplete(isAutocomplete).build();
|
|
||||||
|
|
||||||
if (!options.isEmpty()) {
|
|
||||||
List<ApplicationCommandInteractionOption> sub_options = SUB_FILTER.apply(options.getFirst().getOptions());
|
|
||||||
if (!sub_options.isEmpty()) {
|
|
||||||
last = InteractionIdentifier.builder()
|
|
||||||
.name(options.getFirst().getName())
|
|
||||||
.type(isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND)
|
|
||||||
.parent(last).build();
|
|
||||||
last = InteractionIdentifier.slashBuilder()
|
|
||||||
.name(sub_options.getFirst().getName())
|
|
||||||
.autocomplete(isAutocomplete)
|
|
||||||
.parent(last).build();
|
|
||||||
}else
|
|
||||||
last = InteractionIdentifier.slashBuilder()
|
|
||||||
.name(options.getFirst().getName())
|
|
||||||
.autocomplete(isAutocomplete)
|
|
||||||
.parent(last).build();
|
|
||||||
}
|
|
||||||
return last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
|
|
||||||
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent;
|
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent;
|
||||||
import net.tomatentum.marinara.interaction.InteractionHandler;
|
import net.tomatentum.marinara.interaction.InteractionHandler;
|
||||||
|
import net.tomatentum.marinara.interaction.commands.annotation.CommandChoices;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
||||||
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
|
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
|
||||||
@@ -20,7 +21,7 @@ public class TestCommand implements InteractionHandler {
|
|||||||
name = "foo",
|
name = "foo",
|
||||||
description = "foo bar is very fooby",
|
description = "foo bar is very fooby",
|
||||||
type = SlashCommandOptionType.STRING,
|
type = SlashCommandOptionType.STRING,
|
||||||
choiceEnum = TestChoiceEnum.class
|
choices = @CommandChoices(cenum = TestChoiceEnum.class)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -21,7 +21,7 @@ dependencies {
|
|||||||
testImplementation(libs.mockito)
|
testImplementation(libs.mockito)
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
implementation(libs.log4j)
|
implementation(libs.slf4j)
|
||||||
implementation(libs.javacord)
|
implementation(libs.javacord)
|
||||||
implementation(libs.geantyref)
|
implementation(libs.geantyref)
|
||||||
implementation(project(":lib"))
|
implementation(project(":lib"))
|
||||||
|
@@ -10,9 +10,9 @@ import org.javacord.api.interaction.SlashCommandOptionChoice;
|
|||||||
import org.javacord.api.interaction.SlashCommandOptionChoiceBuilder;
|
import org.javacord.api.interaction.SlashCommandOptionChoiceBuilder;
|
||||||
import org.javacord.api.interaction.SlashCommandOptionType;
|
import org.javacord.api.interaction.SlashCommandOptionType;
|
||||||
|
|
||||||
import net.tomatentum.marinara.interaction.commands.CommandConverter;
|
|
||||||
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
||||||
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
|
import net.tomatentum.marinara.interaction.ident.RootCommandIdentifier;
|
||||||
|
import net.tomatentum.marinara.wrapper.CommandConverter;
|
||||||
|
|
||||||
public class JavacordConverterSpec implements CommandConverter.Spec<SlashCommandBuilder, SlashCommandOption, SlashCommandOptionChoice> {
|
public class JavacordConverterSpec implements CommandConverter.Spec<SlashCommandBuilder, SlashCommandOption, SlashCommandOptionChoice> {
|
||||||
|
|
||||||
@@ -51,6 +51,10 @@ public class JavacordConverterSpec implements CommandConverter.Spec<SlashCommand
|
|||||||
.setDescription(option.description())
|
.setDescription(option.description())
|
||||||
.setRequired(option.required())
|
.setRequired(option.required())
|
||||||
.setAutocompletable(option.autocomplete())
|
.setAutocompletable(option.autocomplete())
|
||||||
|
.setMinLength(Double.valueOf(option.range().min()).longValue())
|
||||||
|
.setDecimalMinValue(option.range().min())
|
||||||
|
.setMaxLength(Double.valueOf(option.range().max()).longValue())
|
||||||
|
.setDecimalMaxValue(option.range().max())
|
||||||
.setChoices(choices)
|
.setChoices(choices)
|
||||||
.build();
|
.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,111 +1,50 @@
|
|||||||
package net.tomatentum.marinara.wrapper.javacord;
|
package net.tomatentum.marinara.wrapper.javacord;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.javacord.api.DiscordApi;
|
import org.javacord.api.DiscordApi;
|
||||||
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.slf4j.Logger;
|
||||||
import org.javacord.api.interaction.SlashCommandInteractionOption;
|
|
||||||
import org.javacord.api.interaction.SlashCommandOption;
|
|
||||||
import org.javacord.api.interaction.SlashCommandOptionChoice;
|
|
||||||
|
|
||||||
import net.tomatentum.marinara.interaction.InteractionType;
|
import net.tomatentum.marinara.wrapper.CommandConverter;
|
||||||
import net.tomatentum.marinara.interaction.commands.CommandConverter;
|
import net.tomatentum.marinara.wrapper.CommandRegisterer;
|
||||||
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
|
|
||||||
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
|
|
||||||
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 CommandConverter<SlashCommandBuilder, SlashCommandOption, SlashCommandOptionChoice> commandConverter;
|
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();
|
||||||
this.commandConverter = CommandConverter.of(new JavacordConverterSpec());
|
var converter = CommandConverter.of(new JavacordConverterSpec());
|
||||||
|
|
||||||
if (api != null)
|
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 void registerSlashCommands(SlashCommandDefinition[] defs) {
|
public CommandRegisterer<?> getRegisterer() {
|
||||||
HashMap<Long, Set<SlashCommandBuilder>> serverCommands = new HashMap<>();
|
return this.commandRegisterer;
|
||||||
Set<SlashCommandBuilder> globalCommands = new HashSet<>();
|
|
||||||
for (SlashCommandDefinition slashCommandDefinition : defs) {
|
|
||||||
SlashCommandBuilder builder = commandConverter.convert(slashCommandDefinition);
|
|
||||||
if (slashCommandDefinition.rootIdentifier().serverIds().length > 0) {
|
|
||||||
for (long serverId : slashCommandDefinition.rootIdentifier().serverIds()) {
|
|
||||||
serverCommands.putIfAbsent(serverId, new HashSet<>());
|
|
||||||
serverCommands.get(serverId).add(builder);
|
|
||||||
}
|
|
||||||
}else
|
|
||||||
globalCommands.add(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (long serverId : serverCommands.keySet()) {
|
|
||||||
api.bulkOverwriteServerApplicationCommands(serverId, serverCommands.get(serverId));
|
|
||||||
}
|
|
||||||
api.bulkOverwriteGlobalApplicationCommands(globalCommands);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InteractionIdentifier getInteractionIdentifier(Object context) {
|
public IdentifierProvider createIdentifierProvider() {
|
||||||
if (context instanceof ButtonInteraction) {
|
return IdentifierProvider.of(
|
||||||
ButtonInteraction button = (ButtonInteraction) context;
|
new SlashCommandIdentifierConverter(),
|
||||||
return InteractionIdentifier.builder().name(button.getCustomId()).type(InteractionType.BUTTON).build();
|
new AutocompleteIdentifierConverter(),
|
||||||
}
|
new ButtonIdentifierConverter()
|
||||||
|
);
|
||||||
if (!(context instanceof SlashCommandInteraction))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
boolean isAutocomplete = false;
|
|
||||||
|
|
||||||
if (context instanceof AutocompleteInteraction)
|
|
||||||
isAutocomplete = true;
|
|
||||||
|
|
||||||
SlashCommandInteraction interaction = (SlashCommandInteraction) context;
|
|
||||||
InteractionIdentifier lastIdentifier = InteractionIdentifier.rootBuilder()
|
|
||||||
.name(interaction.getCommandName())
|
|
||||||
.autocomplete(isAutocomplete)
|
|
||||||
.build();
|
|
||||||
List<SlashCommandInteractionOption> options = interaction.getOptions();
|
|
||||||
if (!options.isEmpty()) {
|
|
||||||
if (!options.getFirst().getArguments().isEmpty()) {
|
|
||||||
lastIdentifier = InteractionIdentifier.builder()
|
|
||||||
.name(options.getFirst().getName())
|
|
||||||
.type(isAutocomplete ? InteractionType.AUTOCOMPLETE : InteractionType.COMMAND)
|
|
||||||
.parent(lastIdentifier)
|
|
||||||
.build();
|
|
||||||
lastIdentifier = InteractionIdentifier.slashBuilder()
|
|
||||||
.name(options.getFirst().getOptions().getFirst().getName())
|
|
||||||
.autocomplete(isAutocomplete)
|
|
||||||
.parent(lastIdentifier)
|
|
||||||
.build();
|
|
||||||
}else
|
|
||||||
lastIdentifier = InteractionIdentifier.slashBuilder()
|
|
||||||
.name(options.getFirst().getName())
|
|
||||||
.autocomplete(isAutocomplete)
|
|
||||||
.parent(lastIdentifier)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return lastIdentifier;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import org.javacord.api.interaction.SlashCommandInteraction;
|
import org.javacord.api.interaction.SlashCommandInteraction;
|
||||||
|
|
||||||
import net.tomatentum.marinara.interaction.InteractionHandler;
|
import net.tomatentum.marinara.interaction.InteractionHandler;
|
||||||
|
import net.tomatentum.marinara.interaction.commands.annotation.CommandChoices;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
||||||
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
|
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
|
||||||
@@ -21,7 +22,7 @@ public class TestCommand implements InteractionHandler {
|
|||||||
name = "foo",
|
name = "foo",
|
||||||
description = "foo bar is very fooby",
|
description = "foo bar is very fooby",
|
||||||
type = SlashCommandOptionType.STRING,
|
type = SlashCommandOptionType.STRING,
|
||||||
choiceEnum = TestChoiceEnum.class
|
choices = @CommandChoices(cenum = TestChoiceEnum.class)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user