diff --git a/.idea/compiler.xml b/.idea/compiler.xml index a67d2dc7..7c12385b 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -12,6 +12,7 @@ + @@ -24,6 +25,7 @@ + diff --git a/.idea/encodings.xml b/.idea/encodings.xml index de06282c..94b979d5 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -6,6 +6,7 @@ + diff --git a/jda/pom.xml b/jda/pom.xml new file mode 100644 index 00000000..8b40cf40 --- /dev/null +++ b/jda/pom.xml @@ -0,0 +1,93 @@ + + + + + 4.0.0 + + + co.aikar + acf-parent + 0.5.0-SNAPSHOT + ../pom.xml + + + acf-jda + 0.5.0-SNAPSHOT + + ACF (JDA) + + + + jcenter + jcenter-bintray + http://jcenter.bintray.com + + + + + + co.aikar + acf-core + 0.5.0-SNAPSHOT + compile + + + net.dv8tion + JDA + 3.5.0_327 + provided + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + ${project.build.directory}/dependency-reduced-pom.xml + + true + + + + + + + + + + diff --git a/jda/src/main/java/co/aikar/commands/CommandEvent.java b/jda/src/main/java/co/aikar/commands/CommandEvent.java new file mode 100644 index 00000000..ce351c19 --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/CommandEvent.java @@ -0,0 +1,50 @@ +package co.aikar.commands; + +import net.dv8tion.jda.core.entities.Message; +import net.dv8tion.jda.core.entities.MessageEmbed; +import net.dv8tion.jda.core.events.message.MessageReceivedEvent; + +public class CommandEvent implements CommandIssuer { + + private MessageReceivedEvent event; + private JDACommandManager manager; + + public CommandEvent(JDACommandManager manager, MessageReceivedEvent event) { + + this.manager = manager; + this.event = event; + } + + @Override + public MessageReceivedEvent getIssuer() { + return event; + } + + @Override + public CommandManager getManager() { + return this.manager; + } + + @Override + public boolean isPlayer() { + return false; + } + + @Override + public boolean hasPermission(String permission) { + // TODO: Permission Resolving + return false; + } + + @Override + public void sendMessageInternal(String message) { + this.event.getChannel().sendMessage(message).queue(); + } + + public void sendMessage(Message message) { + this.event.getChannel().sendMessage(message).queue(); + } + public void sendMessage(MessageEmbed message) { + this.event.getChannel().sendMessage(message).queue(); + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDACommandCompletions.java b/jda/src/main/java/co/aikar/commands/JDACommandCompletions.java new file mode 100644 index 00000000..23bf2663 --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDACommandCompletions.java @@ -0,0 +1,41 @@ +package co.aikar.commands; + +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class JDACommandCompletions extends CommandCompletions> { + private boolean initialized; + public JDACommandCompletions(CommandManager manager) { + super(manager); + this.initialized = true; + } + + @Override + public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler> handler) { + if (initialized) { + throw new UnsupportedOperationException("JDA Doesn't support Command Completions"); + } + return null; + } + + @Override + public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler> handler) { + if (initialized) { + throw new UnsupportedOperationException("JDA Doesn't support Command Completions"); + } + return null; + } + + @NotNull + @Override + List of(RegisteredCommand command, CommandIssuer sender, String[] completionInfo, String[] args, boolean isAsync) { + return ImmutableList.of(); + } + + @Override + List getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) { + return ImmutableList.of(); + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDACommandContexts.java b/jda/src/main/java/co/aikar/commands/JDACommandContexts.java new file mode 100644 index 00000000..a745bff8 --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDACommandContexts.java @@ -0,0 +1,7 @@ +package co.aikar.commands; + +public class JDACommandContexts extends CommandContexts { + JDACommandContexts(CommandManager manager) { + super(manager); + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDACommandExecutionContext.java b/jda/src/main/java/co/aikar/commands/JDACommandExecutionContext.java new file mode 100644 index 00000000..41c6cdfd --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDACommandExecutionContext.java @@ -0,0 +1,11 @@ +package co.aikar.commands; + +import java.lang.reflect.Parameter; +import java.util.List; +import java.util.Map; + +public class JDACommandExecutionContext extends CommandExecutionContext { + JDACommandExecutionContext(RegisteredCommand cmd, Parameter param, CommandEvent sender, List args, int index, Map passedArgs) { + super(cmd, param, sender, args, index, passedArgs); + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDACommandManager.java b/jda/src/main/java/co/aikar/commands/JDACommandManager.java new file mode 100644 index 00000000..a4773a0b --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDACommandManager.java @@ -0,0 +1,170 @@ +package co.aikar.commands; + +import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil; +import com.google.common.collect.Maps; +import jdk.nashorn.internal.ir.IfNode; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.entities.Message; +import net.dv8tion.jda.core.events.message.MessageReceivedEvent; + +import java.lang.reflect.Parameter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class JDACommandManager extends CommandManager< + MessageReceivedEvent, + CommandEvent, + String, + MessageFormatter, + JDACommandExecutionContext, + JDAConditionContext + > { + + private final JDA jda; + private String startsWith; + private Logger logger; + protected JDACommandCompletions completions; + protected JDACommandContexts contexts; + protected JDALocales locales; + + protected Map commands = Maps.newHashMap(); + + public JDACommandManager(JDA jda) { + this(jda, "!"); + } + public JDACommandManager(JDA jda, String startsWith) { + this.jda = jda; + jda.addEventListener(new JDAListener(this)); + this.startsWith = startsWith; + this.completions = new JDACommandCompletions(this); + this.logger = Logger.getLogger(this.getClass().getSimpleName()); + } + + public JDA getJDA() { + return jda; + } + + public Logger getLogger() { + return logger; + } + + public void setLogger(Logger logger) { + this.logger = logger; + } + + public String getStartsWith() { + return startsWith; + } + + public void setStartsWith(String startsWith) { + this.startsWith = startsWith; + } + + @Override + public CommandContexts getCommandContexts() { + if (this.contexts == null) { + this.contexts = new JDACommandContexts(this); + } + return null; + } + + @Override + public CommandCompletions getCommandCompletions() { + return this.completions; + } + + @Override + public void registerCommand(BaseCommand command) { + for (Map.Entry entry : command.registeredCommands.entrySet()) { + String commandName = entry.getKey().toLowerCase(); + JDARootCommand cmd = (JDARootCommand) entry.getValue(); + if (!cmd.isRegistered) { + cmd.isRegistered = true; + commands.put(commandName, cmd); + } + } + } + + @Override + public boolean hasRegisteredCommands() { + return !this.commands.isEmpty(); + } + + @Override + public boolean isCommandIssuer(Class type) { + return CommandEvent.class.isAssignableFrom(type); + } + + @Override + public CommandEvent getCommandIssuer(Object issuer) { + if (!(issuer instanceof MessageReceivedEvent)) { + throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Message Received Event."); + } + return new CommandEvent(this, (MessageReceivedEvent) issuer); + } + + @Override + public RootCommand createRootCommand(String cmd) { + return new JDARootCommand(this, cmd); + } + + @Override + public Locales getLocales() { + if (this.locales == null) { + this.locales = new JDALocales(this); + this.locales.loadLanguages(); + } + return null; + } + + @Override + public CommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + return new JDACommandExecutionContext(command, parameter, (CommandEvent) sender, args, i, passedArgs); + } + + @Override + public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) { + // Not really going to be used; + //noinspection unchecked + return new CommandCompletionContext(command, sender, input, config, args); + } + + @Override + public void log(LogLevel level, String message, Throwable throwable) { + Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE; + logger.log(logLevel, LogLevel.LOG_PREFIX + message); + if (throwable != null) { + for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) { + logger.log(logLevel, LogLevel.LOG_PREFIX + line); + } + } + } + + void dispatchEvent(MessageReceivedEvent event) { + Message message = event.getMessage(); + String msg = message.getContentDisplay(); + + if (!msg.startsWith(this.startsWith)) { + return; + } + + String[] args = ACFPatterns.SPACE.split(msg.substring(1), -1); + if (args.length == 0) { + return; + } + String cmd = args[0].toLowerCase(); + JDARootCommand rootCommand = this.commands.get(cmd); + if (rootCommand == null) { + return; + } + if (args.length > 1) { + args = Arrays.copyOfRange(args, 1, args.length); + } else { + args = new String[0]; + } + rootCommand.execute(this.getCommandIssuer(event), cmd, args); + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDAConditionContext.java b/jda/src/main/java/co/aikar/commands/JDAConditionContext.java new file mode 100644 index 00000000..154e3c5c --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDAConditionContext.java @@ -0,0 +1,7 @@ +package co.aikar.commands; + +public class JDAConditionContext extends ConditionContext { + JDAConditionContext(CommandEvent issuer, String config) { + super(issuer, config); + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDAListener.java b/jda/src/main/java/co/aikar/commands/JDAListener.java new file mode 100644 index 00000000..4b1ea349 --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDAListener.java @@ -0,0 +1,33 @@ +package co.aikar.commands; + +import net.dv8tion.jda.core.entities.ChannelType; +import net.dv8tion.jda.core.events.message.MessageReceivedEvent; +import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.core.events.message.priv.PrivateMessageReceivedEvent; +import net.dv8tion.jda.core.hooks.ListenerAdapter; + +public class JDAListener extends ListenerAdapter { + + private final JDACommandManager manager; + + JDAListener(JDACommandManager manager) { + + this.manager = manager; + } + @Override + public void onGuildMessageReceived(GuildMessageReceivedEvent event) { + super.onGuildMessageReceived(event); + } + + @Override + public void onPrivateMessageReceived(PrivateMessageReceivedEvent event) { + super.onPrivateMessageReceived(event); + } + + @Override + public void onMessageReceived(MessageReceivedEvent event) { + if (event.isFromType(ChannelType.TEXT) || event.isFromType(ChannelType.PRIVATE)) { + this.manager.dispatchEvent(event); + } + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDALocales.java b/jda/src/main/java/co/aikar/commands/JDALocales.java new file mode 100644 index 00000000..84898f4d --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDALocales.java @@ -0,0 +1,7 @@ +package co.aikar.commands; + +public class JDALocales extends Locales { + public JDALocales(CommandManager manager) { + super(manager); + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDAMessageFormatter.java b/jda/src/main/java/co/aikar/commands/JDAMessageFormatter.java new file mode 100644 index 00000000..21d24d79 --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDAMessageFormatter.java @@ -0,0 +1,8 @@ +package co.aikar.commands; + +public class JDAMessageFormatter extends MessageFormatter { + @Override + String format(String color, String message) { + return message; + } +} diff --git a/jda/src/main/java/co/aikar/commands/JDARootCommand.java b/jda/src/main/java/co/aikar/commands/JDARootCommand.java new file mode 100644 index 00000000..aa000d65 --- /dev/null +++ b/jda/src/main/java/co/aikar/commands/JDARootCommand.java @@ -0,0 +1,51 @@ +package co.aikar.commands; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.SetMultimap; + +import java.util.ArrayList; +import java.util.List; + +public class JDARootCommand implements RootCommand { + + private JDACommandManager manager; + private final String name; + private BaseCommand defCommand; + private SetMultimap subCommands = HashMultimap.create(); + private List children = new ArrayList<>(); + boolean isRegistered = false; + + JDARootCommand(JDACommandManager manager, String name) { + this.manager = manager; + this.name = name; + } + + @Override + + public void addChild(BaseCommand command) { + if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) { + this.defCommand = command; + } + addChildShared(this.children, this.subCommands, command); + } + + @Override + public CommandManager getManager() { + return this.manager; + } + + @Override + public SetMultimap getSubCommands() { + return this.subCommands; + } + + @Override + public List getChildren() { + return this.children; + } + + @Override + public String getCommandName() { + return this.name; + } +} diff --git a/pom.xml b/pom.xml index 6d82931e..f15df29f 100644 --- a/pom.xml +++ b/pom.xml @@ -147,5 +147,6 @@ paper bungee sponge + jda