Make slash commands interface and load them dynamically
All checks were successful
continuous-integration/drone/push Build is passing

Slash commands are now loaded dynamically by implementing a SlashCommand interface and storing them in a loaded commands map.
This commit is contained in:
Bea 2022-11-22 14:32:22 +01:00
parent 7ae4790d5c
commit 882c695484
13 changed files with 133 additions and 26 deletions

View File

@ -6,6 +6,7 @@ import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.requests.GatewayIntent;
import sun.misc.Signal; import sun.misc.Signal;
import wtf.beatrice.hidekobot.commands.slash.*;
import wtf.beatrice.hidekobot.datasource.ConfigurationSource; import wtf.beatrice.hidekobot.datasource.ConfigurationSource;
import wtf.beatrice.hidekobot.datasource.DatabaseSource; import wtf.beatrice.hidekobot.datasource.DatabaseSource;
import wtf.beatrice.hidekobot.listeners.ButtonInteractionListener; import wtf.beatrice.hidekobot.listeners.ButtonInteractionListener;
@ -97,9 +98,21 @@ public class HidekoBot
} }
// register commands
SlashCommandListener slashCommandListener = new SlashCommandListener();
slashCommandListener.registerCommand(new AvatarCommand());
slashCommandListener.registerCommand(new BotInfoCommand());
slashCommandListener.registerCommand(new ClearCommand());
slashCommandListener.registerCommand(new CoinFlipCommand());
slashCommandListener.registerCommand(new DieCommand());
slashCommandListener.registerCommand(new HelpCommand());
slashCommandListener.registerCommand(new InviteCommand());
slashCommandListener.registerCommand(new PingCommand());
slashCommandListener.registerCommand(new SayCommand());
// register listeners // register listeners
jda.addEventListener(new MessageListener()); jda.addEventListener(new MessageListener());
jda.addEventListener(new SlashCommandListener()); jda.addEventListener(slashCommandListener);
jda.addEventListener(new SlashCommandCompleter()); jda.addEventListener(new SlashCommandCompleter());
jda.addEventListener(new ButtonInteractionListener()); jda.addEventListener(new ButtonInteractionListener());

View File

@ -6,10 +6,17 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEve
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.objects.SlashCommand;
public class AvatarCommand public class AvatarCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "avatar";
}
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
// defer reply because this might take a moment // defer reply because this might take a moment

View File

@ -6,15 +6,22 @@ import net.dv8tion.jda.api.interactions.commands.Command;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.HidekoBot; import wtf.beatrice.hidekobot.HidekoBot;
import wtf.beatrice.hidekobot.objects.SlashCommand;
import wtf.beatrice.hidekobot.util.FormatUtil; import wtf.beatrice.hidekobot.util.FormatUtil;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.List; import java.util.List;
public class BotInfoCommand public class BotInfoCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "botinfo";
}
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
// defer reply because this might take a moment // defer reply because this might take a moment

View File

@ -13,13 +13,21 @@ import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.requests.restaction.WebhookMessageEditAction; import net.dv8tion.jda.api.requests.restaction.WebhookMessageEditAction;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.objects.SlashCommand;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ClearCommand public class ClearCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "clear";
}
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {

View File

@ -9,16 +9,23 @@ import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.interactions.components.buttons.Button;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.objects.SlashCommand;
import wtf.beatrice.hidekobot.util.RandomUtil; import wtf.beatrice.hidekobot.util.RandomUtil;
import java.util.List; import java.util.List;
public class CoinFlipCommand public class CoinFlipCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "coinflip";
}
private final Button reflipButton = Button.primary("coinflip_reflip", "Flip again") private final Button reflipButton = Button.primary("coinflip_reflip", "Flip again")
.withEmoji(Emoji.fromFormatted("\uD83E\uDE99")); .withEmoji(Emoji.fromFormatted("\uD83E\uDE99"));
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
// perform coin flip // perform coin flip

View File

@ -4,13 +4,20 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEve
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.HidekoBot; import wtf.beatrice.hidekobot.HidekoBot;
import wtf.beatrice.hidekobot.objects.SlashCommand;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class DieCommand public class DieCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "die";
}
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
if(Cache.getBotOwnerId() != event.getUser().getIdLong()) if(Cache.getBotOwnerId() != event.getUser().getIdLong())

View File

@ -4,10 +4,17 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.objects.SlashCommand;
public class HelpCommand public class HelpCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "help";
}
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
// defer reply because replying might take a while // defer reply because replying might take a while

View File

@ -11,9 +11,17 @@ import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.HidekoBot; import wtf.beatrice.hidekobot.HidekoBot;
import wtf.beatrice.hidekobot.objects.SlashCommand;
public class InviteCommand public class InviteCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "invite";
}
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
// defer reply because this might take a moment // defer reply because this might take a moment

View File

@ -2,9 +2,16 @@ package wtf.beatrice.hidekobot.commands.slash;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.objects.SlashCommand;
public class PingCommand public class PingCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "ping";
}
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
event.reply("Pong!").queue(); event.reply("Pong!").queue();

View File

@ -4,10 +4,18 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.objects.SlashCommand;
public class SayCommand public class SayCommand implements SlashCommand
{ {
@Override
public String getCommandName() {
return "say";
}
@Override
public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) public void runSlashCommand(@NotNull SlashCommandInteractionEvent event)
{ {
MessageChannel channel = event.getChannel(); MessageChannel channel = event.getChannel();

View File

@ -10,6 +10,12 @@ import wtf.beatrice.hidekobot.util.Logger;
public class MessageListener extends ListenerAdapter public class MessageListener extends ListenerAdapter
{ {
private final String commandRegex = "(?i)^(hideko|hde)\\b";
// (?i) -> case insensitive flag
// ^ -> start of string (not in middle of a sentence)
// \b -> the word has to end here
// .* -> there can be anything else after this word
private final Logger logger = new Logger(MessageListener.class); private final Logger logger = new Logger(MessageListener.class);
@Override @Override
@ -17,24 +23,31 @@ public class MessageListener extends ListenerAdapter
{ {
String eventMessage = event.getMessage().getContentDisplay(); String eventMessage = event.getMessage().getContentDisplay();
if(!eventMessage.toLowerCase().matches(commandRegex + ".*"))
return;
MessageChannel channel = event.getChannel();
// generate args from the string
String argsString = eventMessage.replaceAll(commandRegex + "\\s*", "");
String[] args = argsString.split("\\s+");
event.getMessage().reply("Hi").queue();
if(eventMessage.equalsIgnoreCase("hideko")) if(eventMessage.equalsIgnoreCase("hideko"))
{ {
MessageChannel channel = event.getChannel();
channel.sendMessage("Hello there! ✨").queue(); channel.sendMessage("Hello there! ✨").queue();
return; return;
} }
if(eventMessage.equalsIgnoreCase("ping")) if(eventMessage.equalsIgnoreCase("ping"))
{ {
MessageChannel channel = event.getChannel();
channel.sendMessage("Pong!").queue(); channel.sendMessage("Pong!").queue();
return; return;
} }
if(eventMessage.equalsIgnoreCase("hideko verbose")) if(eventMessage.equalsIgnoreCase("hideko verbose"))
{ {
MessageChannel channel = event.getChannel();
boolean verbose = Cache.isVerbose(); boolean verbose = Cache.isVerbose();
String msg = verbose ? "off" : "on"; String msg = verbose ? "off" : "on";

View File

@ -3,24 +3,28 @@ package wtf.beatrice.hidekobot.listeners;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import wtf.beatrice.hidekobot.commands.slash.*; import wtf.beatrice.hidekobot.objects.SlashCommand;
import java.util.HashMap;
public class SlashCommandListener extends ListenerAdapter public class SlashCommandListener extends ListenerAdapter
{ {
HashMap<String, SlashCommand> registeredCommands = new HashMap<>();
public void registerCommand(SlashCommand command)
{
registeredCommands.remove(command.getCommandName());
registeredCommands.put(command.getCommandName(), command);
}
@Override @Override
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event)
{ {
switch (event.getName().toLowerCase()) { String commandName = event.getName().toLowerCase();
case "avatar" -> new AvatarCommand().runSlashCommand(event); SlashCommand command = registeredCommands.get(commandName);
case "botinfo" -> new BotInfoCommand().runSlashCommand(event); if(command == null) return;
case "clear" -> new ClearCommand().runSlashCommand(event);
case "coinflip" -> new CoinFlipCommand().runSlashCommand(event); command.runSlashCommand(event);
case "die" -> new DieCommand().runSlashCommand(event);
case "help" -> new HelpCommand().runSlashCommand(event);
case "invite" -> new InviteCommand().runSlashCommand(event);
case "ping" -> new PingCommand().runSlashCommand(event);
case "say" -> new SayCommand().runSlashCommand(event);
}
} }
} }

View File

@ -0,0 +1,11 @@
package wtf.beatrice.hidekobot.objects;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.jetbrains.annotations.NotNull;
public interface SlashCommand
{
String getCommandName();
void runSlashCommand(@NotNull SlashCommandInteractionEvent event);
}