mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2025-01-26 22:21:31 +01:00
Progress on running commands from Discord
This commit is contained in:
parent
c1edd44751
commit
383a7ad97a
@ -1,12 +0,0 @@
|
||||
package com.discordsrv.bukkit;
|
||||
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class PaperCmdMap {
|
||||
|
||||
public static Set<String> getMap(Server server) {
|
||||
return server.getCommandMap().getKnownCommands().keySet();
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.discordsrv.bukkit;
|
||||
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class PaperCommandMap {
|
||||
|
||||
public static final boolean IS_AVAILABLE;
|
||||
|
||||
static {
|
||||
boolean is = false;
|
||||
try {
|
||||
Class<?> serverClass = Server.class;
|
||||
serverClass.getDeclaredMethod("getCommandMap");
|
||||
is = true;
|
||||
} catch (Throwable ignored) {}
|
||||
IS_AVAILABLE = is;
|
||||
}
|
||||
|
||||
public static Set<String> getKnownCommands(Server server) {
|
||||
return server.getCommandMap().getKnownCommands().keySet();
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
package com.discordsrv.bukkit;
|
||||
|
||||
import com.discordsrv.api.DiscordSRVApi;
|
||||
import com.discordsrv.bukkit.command.game.BukkitAutoCompleteHelper;
|
||||
import com.discordsrv.bukkit.command.game.handler.AbstractBukkitCommandHandler;
|
||||
import com.discordsrv.bukkit.component.translation.BukkitTranslationLoader;
|
||||
import com.discordsrv.bukkit.config.connection.BukkitConnectionConfig;
|
||||
@ -48,14 +49,11 @@ import com.discordsrv.common.messageforwarding.game.minecrafttodiscord.Minecraft
|
||||
import com.discordsrv.common.plugin.PluginManager;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -70,6 +68,7 @@ public class BukkitDiscordSRV extends ServerDiscordSRV<DiscordSRVBukkitBootstrap
|
||||
private final BukkitPluginManager pluginManager;
|
||||
private AbstractBukkitCommandHandler commandHandler;
|
||||
private final BukkitRequiredLinkingListener requiredLinkingListener;
|
||||
private final BukkitAutoCompleteHelper autoCompleteHelper;
|
||||
|
||||
private final BukkitConnectionConfigManager connectionConfigManager;
|
||||
private final BukkitConfigManager configManager;
|
||||
@ -98,6 +97,7 @@ public class BukkitDiscordSRV extends ServerDiscordSRV<DiscordSRVBukkitBootstrap
|
||||
load();
|
||||
|
||||
this.requiredLinkingListener = new BukkitRequiredLinkingListener(this);
|
||||
this.autoCompleteHelper = new BukkitAutoCompleteHelper(this);
|
||||
}
|
||||
|
||||
public JavaPlugin plugin() {
|
||||
@ -231,38 +231,6 @@ public class BukkitDiscordSRV extends ServerDiscordSRV<DiscordSRVBukkitBootstrap
|
||||
}
|
||||
|
||||
public ExecuteCommand.AutoCompleteHelper autoCompleteHelper() {
|
||||
return parts -> {
|
||||
String commandName = !parts.isEmpty() ? parts.remove(0) : null;
|
||||
Command command = commandName != null ? server().getPluginCommand(commandName) : null;
|
||||
if (command == null) {
|
||||
if (parts.size() > 1) {
|
||||
// Command is not known but there are arguments, nothing to auto complete...
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
// List out commands
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
for (String cmd : PaperCmdMap.getMap(server())) {
|
||||
if (commandName == null || cmd.startsWith(commandName)) {
|
||||
suggestions.add(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the arguments minus the last one (if any)
|
||||
String prefix = String.join(" ", parts.subList(0, parts.size() - (!parts.isEmpty() ? 1 : 0)));
|
||||
if (!prefix.isEmpty()) {
|
||||
prefix = prefix + " ";
|
||||
}
|
||||
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
for (String suggestion : command.tabComplete(server().getConsoleSender(), commandName, parts.toArray(new String[0]))) {
|
||||
suggestions.add(commandName + " " + prefix + suggestion);
|
||||
}
|
||||
|
||||
return suggestions;
|
||||
};
|
||||
return autoCompleteHelper;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
package com.discordsrv.bukkit.command.game;
|
||||
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.bukkit.PaperCommandMap;
|
||||
import com.discordsrv.common.command.discord.commands.subcommand.ExecuteCommand;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BukkitAutoCompleteHelper implements ExecuteCommand.AutoCompleteHelper {
|
||||
|
||||
private final BukkitDiscordSRV discordSRV;
|
||||
|
||||
public BukkitAutoCompleteHelper(BukkitDiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<String>> suggestCommands(List<String> parts) {
|
||||
String commandName = !parts.isEmpty() ? parts.remove(0) : null;
|
||||
Command command = commandName != null ? discordSRV.server().getPluginCommand(commandName) : null;
|
||||
if (command == null) {
|
||||
if (parts.size() > 1) {
|
||||
// Command is not known but there are arguments, nothing to auto complete...
|
||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||
} else {
|
||||
// List out commands
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
|
||||
if (PaperCommandMap.IS_AVAILABLE) {
|
||||
// If Paper's CommandMap is available we can list out 'root' commands
|
||||
CompletableFuture<List<String>> future = new CompletableFuture<>();
|
||||
discordSRV.scheduler().runOnMainThread(() -> {
|
||||
try {
|
||||
for (String cmd : PaperCommandMap.getKnownCommands(discordSRV.server())) {
|
||||
if (commandName == null || cmd.startsWith(commandName)) {
|
||||
suggestions.add(cmd);
|
||||
}
|
||||
}
|
||||
future.complete(suggestions);
|
||||
} catch (Throwable t) {
|
||||
future.completeExceptionally(t);
|
||||
}
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the arguments minus the last one (if any)
|
||||
String prefix = String.join(" ", parts.subList(0, parts.size() - (!parts.isEmpty() ? 1 : 0)));
|
||||
if (!prefix.isEmpty()) {
|
||||
prefix = prefix + " ";
|
||||
}
|
||||
|
||||
CompletableFuture<List<String>> future = new CompletableFuture<>();
|
||||
String finalPrefix = prefix;
|
||||
discordSRV.scheduler().runOnMainThread(() -> {
|
||||
try {
|
||||
CommandSender commandSender = discordSRV.server().getConsoleSender();
|
||||
List<String> completions = command.tabComplete(commandSender, commandName, parts.toArray(new String[0]));
|
||||
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
for (String suggestion : completions) {
|
||||
suggestions.add(commandName + " " + finalPrefix + suggestion);
|
||||
}
|
||||
future.complete(suggestions);
|
||||
} catch (Throwable t) {
|
||||
future.completeExceptionally(t);
|
||||
}
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
}
|
@ -153,6 +153,7 @@ public interface DiscordSRV extends DiscordSRVApi {
|
||||
List<ReloadResult> runReload(Set<ReloadFlag> flags, boolean silent);
|
||||
CompletableFuture<Void> invokeDisable();
|
||||
|
||||
@Nullable
|
||||
default ExecuteCommand.AutoCompleteHelper autoCompleteHelper() {
|
||||
return null;
|
||||
}
|
||||
|
@ -6,11 +6,17 @@ import com.discordsrv.api.discord.entity.interaction.component.ComponentIdentifi
|
||||
import com.discordsrv.api.discord.events.interaction.command.DiscordChatInputInteractionEvent;
|
||||
import com.discordsrv.api.discord.events.interaction.command.DiscordCommandAutoCompleteInteractionEvent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.discordsrv.common.logging.NamedLogger;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ExecuteCommand implements Consumer<DiscordChatInputInteractionEvent>, DiscordCommand.AutoCompleteHandler {
|
||||
@ -36,9 +42,11 @@ public class ExecuteCommand implements Consumer<DiscordChatInputInteractionEvent
|
||||
}
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final Logger logger;
|
||||
|
||||
public ExecuteCommand(DiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.logger = new NamedLogger(discordSRV, "EXECUTE_COMMAND");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,12 +71,25 @@ public class ExecuteCommand implements Consumer<DiscordChatInputInteractionEvent
|
||||
List<String> parts = new ArrayList<>(Arrays.asList(command.split(" ")));
|
||||
|
||||
AutoCompleteHelper helper = discordSRV.autoCompleteHelper();
|
||||
if (helper == null) {
|
||||
// No suggestions available.
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> suggestions = getSuggestions(helper, parts);
|
||||
if (suggestions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> suggestions = helper.suggestCommands(new ArrayList<>(parts));
|
||||
if (suggestions.isEmpty() || suggestions.contains(command)) {
|
||||
parts.add("");
|
||||
suggestions = new ArrayList<>(helper.suggestCommands(parts));
|
||||
|
||||
List<String> newSuggestions = getSuggestions(helper, parts);
|
||||
if (newSuggestions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
suggestions = new ArrayList<>(newSuggestions);
|
||||
if (suggestions.isEmpty()) {
|
||||
suggestions.add(command);
|
||||
}
|
||||
@ -81,8 +102,25 @@ public class ExecuteCommand implements Consumer<DiscordChatInputInteractionEvent
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getSuggestions(AutoCompleteHelper helper, List<String> parts) {
|
||||
try {
|
||||
return helper.suggestCommands(new ArrayList<>(parts)).get(2, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return null;
|
||||
} catch (TimeoutException e) {
|
||||
return null;
|
||||
} catch (ExecutionException e) {
|
||||
logger.error("Failed to suggest commands", e.getCause());
|
||||
return null;
|
||||
} catch (Throwable t) {
|
||||
logger.error("Failed to suggest commands", t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface AutoCompleteHelper {
|
||||
|
||||
List<String> suggestCommands(List<String> parts);
|
||||
CompletableFuture<List<String>> suggestCommands(List<String> parts);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package com.discordsrv.common.config.main;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
@ConfigSerializable
|
||||
public class DiscordCommandConfig {
|
||||
|
||||
public ExecuteConfig execute = new ExecuteConfig();
|
||||
|
||||
@ConfigSerializable
|
||||
public static class ExecuteConfig {
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.discordsrv.common.config.main.generic;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ConfigSerializable
|
||||
public class GameCommandFilterConfig {
|
||||
|
||||
@Comment("true for blacklist (blocking commands), false for whitelist (allowing commands)")
|
||||
public boolean blacklist = true;
|
||||
|
||||
@Comment("The role and user ids which this set of allowed/blocked commands is for")
|
||||
public List<Long> roleAndUserIds = new ArrayList<>();
|
||||
|
||||
@Comment("The commands that are allowed/blocked. Use / at the beginning and end of a value for a regular expression (regex)")
|
||||
public List<String> commands = new ArrayList<>();
|
||||
}
|
Loading…
Reference in New Issue
Block a user