From 47e8332931eefd5b3a0a76a705af64c5cdb2844e Mon Sep 17 00:00:00 2001 From: anthorob Date: Tue, 25 Jun 2024 23:49:58 -0400 Subject: [PATCH] Implement command results in execute function --- .../java/netneutrality/NetNeutrality.java | 2 +- .../command/AbstractCommand.java | 3 +- .../command/CommandExecutionResult.java | 64 ++++++++++ .../{core => command}/CommandManager.java | 5 +- .../java/netneutrality/command/ICommand.java | 4 +- .../command/admin/BlacklistCommand.java | 9 +- .../command/basic/HelpCommand.java | 8 +- .../command/basic/PingCommand.java | 9 +- .../command/bot/ConfigureCommand.java | 33 +++--- .../command/crypto/CryptoPriceCommand.java | 16 ++- .../command/music/BitconnectCommand.java | 8 +- .../command/music/ClearQueueCommand.java | 26 ++-- .../music/CurrentlyPlayingCommand.java | 8 +- .../command/music/JoinCommand.java | 20 ++-- .../command/music/LeaveCommand.java | 9 +- .../command/music/PlayCommand.java | 7 +- .../command/music/QueueCommand.java | 40 ++----- .../command/music/ShuffleCommand.java | 8 +- .../command/music/SkipCommand.java | 20 ++-- .../command/music/StopCommand.java | 14 ++- .../command/music/ViewQueueCommand.java | 10 +- .../command/music/VolumeCommand.java | 13 +- .../command/music/VoteSkipCommand.java | 11 +- .../netneutrality/core/CommandProcessor.java | 111 ++++++++++++++++++ .../core/context/CommandContext.java | 2 - .../core/context/MessageCommandContext.java | 39 ------ .../core/context/SlashCommandContext.java | 39 ++---- .../hooks/SlashCommandHooks.java | 5 +- .../hooks/message/MessageReceivedHandler.java | 5 +- .../netneutrality/music/MusicManager.java | 30 ++--- .../netneutrality/music/QueueManager.java | 72 +++++++++--- .../MusicPlayerAutoDisconnectThread.java | 8 +- .../netneutrality/utils/MessageFunction.java | 2 +- 33 files changed, 419 insertions(+), 241 deletions(-) create mode 100644 src/main/java/netneutrality/command/CommandExecutionResult.java rename src/main/java/netneutrality/{core => command}/CommandManager.java (97%) create mode 100644 src/main/java/netneutrality/core/CommandProcessor.java diff --git a/src/main/java/netneutrality/NetNeutrality.java b/src/main/java/netneutrality/NetNeutrality.java index 3f5aa07..aaa9b7c 100644 --- a/src/main/java/netneutrality/NetNeutrality.java +++ b/src/main/java/netneutrality/NetNeutrality.java @@ -13,7 +13,7 @@ import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.exceptions.InvalidTokenException; import net.dv8tion.jda.api.requests.GatewayIntent; -import netneutrality.core.CommandManager; +import netneutrality.command.CommandManager; import netneutrality.core.LogHandler; import netneutrality.db.DBController; import netneutrality.hooks.SlashCommandHooks; diff --git a/src/main/java/netneutrality/command/AbstractCommand.java b/src/main/java/netneutrality/command/AbstractCommand.java index 158970d..c098e8d 100644 --- a/src/main/java/netneutrality/command/AbstractCommand.java +++ b/src/main/java/netneutrality/command/AbstractCommand.java @@ -36,7 +36,8 @@ public abstract class AbstractCommand implements ICommand { @Deprecated @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { // Prefer slash commands + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/CommandExecutionResult.java b/src/main/java/netneutrality/command/CommandExecutionResult.java new file mode 100644 index 0000000..fd51e64 --- /dev/null +++ b/src/main/java/netneutrality/command/CommandExecutionResult.java @@ -0,0 +1,64 @@ +package netneutrality.command; +/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +public class CommandExecutionResult { + + public enum Result { + SUCCESS, INFO, WARN, ERROR, NOACTION + } + + private final Result result; + private final String message; + private final Exception exception; + + private CommandExecutionResult(Result result, String message, Exception exception) { + this.result = result; + this.message = message; + this.exception = exception; + } + + private CommandExecutionResult(Result result, String message) { + this(result, message, null); + } + + public Result getResult() { + return result; + } + + public String getMessage() { + return message; + } + + public Exception getException() { + return exception; + } + + public static CommandExecutionResult success(String message) { + return new CommandExecutionResult(Result.SUCCESS, message); + } + + public static CommandExecutionResult info(String message) { + return new CommandExecutionResult(Result.INFO, message); + } + + public static CommandExecutionResult warn(String message) { + return new CommandExecutionResult(Result.WARN, message); + } + + public static CommandExecutionResult error(String message, Exception exception) { + return new CommandExecutionResult(Result.ERROR, message, exception); + } + + public static CommandExecutionResult error(String message) { + return error(message, null); + } + + public static CommandExecutionResult none() { + return new CommandExecutionResult(Result.NOACTION, null); + } + +} diff --git a/src/main/java/netneutrality/core/CommandManager.java b/src/main/java/netneutrality/command/CommandManager.java similarity index 97% rename from src/main/java/netneutrality/core/CommandManager.java rename to src/main/java/netneutrality/command/CommandManager.java index f3f599b..1f9cd28 100644 --- a/src/main/java/netneutrality/core/CommandManager.java +++ b/src/main/java/netneutrality/command/CommandManager.java @@ -1,5 +1,4 @@ -package netneutrality.core; - +package netneutrality.command; /* * Copyright (c) anthorob * @@ -11,7 +10,7 @@ import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction; import netneutrality.NetNeutrality; -import netneutrality.command.AbstractCommand; +import netneutrality.core.LogHandler; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.reflections.Reflections; diff --git a/src/main/java/netneutrality/command/ICommand.java b/src/main/java/netneutrality/command/ICommand.java index 19b3a2d..c7af286 100644 --- a/src/main/java/netneutrality/command/ICommand.java +++ b/src/main/java/netneutrality/command/ICommand.java @@ -38,7 +38,7 @@ public interface ICommand { boolean canBeExecutedFrom(Guild guild, MessageChannel channel); @Deprecated - void execute(MessageCommandContext context); + CommandExecutionResult execute(MessageCommandContext context); - void execute(SlashCommandContext context); + CommandExecutionResult execute(SlashCommandContext context); } diff --git a/src/main/java/netneutrality/command/admin/BlacklistCommand.java b/src/main/java/netneutrality/command/admin/BlacklistCommand.java index 86be8b1..b50f31f 100644 --- a/src/main/java/netneutrality/command/admin/BlacklistCommand.java +++ b/src/main/java/netneutrality/command/admin/BlacklistCommand.java @@ -11,6 +11,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import netneutrality.command.AbstractCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.command.CommandType; import netneutrality.core.LogHandler; import netneutrality.core.context.MessageCommandContext; @@ -70,12 +71,12 @@ public class BlacklistCommand extends AbstractCommand { } @Override - public void execute(MessageCommandContext context) { - + public CommandExecutionResult execute(MessageCommandContext context) { + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { String sub = context.getEvent().getFullCommandName().split(" ")[1]; DBBlacklist controller = DBController.get(DBBlacklist.class); String word = context.getEvent().getOption("word", "", OptionMapping::getAsString); @@ -106,5 +107,7 @@ public class BlacklistCommand extends AbstractCommand { case "disable" -> controller.disable(word, context); case "enable" -> controller.enable(word, context); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/basic/HelpCommand.java b/src/main/java/netneutrality/command/basic/HelpCommand.java index 0ec10e7..0648a7d 100644 --- a/src/main/java/netneutrality/command/basic/HelpCommand.java +++ b/src/main/java/netneutrality/command/basic/HelpCommand.java @@ -9,6 +9,7 @@ import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import netneutrality.command.AbstractCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.command.CommandType; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; @@ -54,7 +55,7 @@ public class HelpCommand extends AbstractCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { if (context.getArgs().length == 0) { List help = MessageFunction.buildHelpMessage(context.getGuildUser()); @@ -62,13 +63,14 @@ public class HelpCommand extends AbstractCommand { context.replyPrivate(help); } + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { List help = MessageFunction.buildHelpMessage(context.getGuildUser()); - context.replyEphemeral("Help has been sent in DM!"); context.sendMessageInPrivate(help); + return CommandExecutionResult.success("Help has been sent in DM!"); } } diff --git a/src/main/java/netneutrality/command/basic/PingCommand.java b/src/main/java/netneutrality/command/basic/PingCommand.java index f832727..02c987d 100644 --- a/src/main/java/netneutrality/command/basic/PingCommand.java +++ b/src/main/java/netneutrality/command/basic/PingCommand.java @@ -7,6 +7,7 @@ package netneutrality.command.basic; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.command.CommandType; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; @@ -49,14 +50,16 @@ public class PingCommand extends AbstractCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { if (context.getArgs().length == 0) context.reply(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing())); + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { - context.reply(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing())); + public CommandExecutionResult execute(SlashCommandContext context) { + return CommandExecutionResult.success(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing())); } } diff --git a/src/main/java/netneutrality/command/bot/ConfigureCommand.java b/src/main/java/netneutrality/command/bot/ConfigureCommand.java index 61bcafa..4b33096 100644 --- a/src/main/java/netneutrality/command/bot/ConfigureCommand.java +++ b/src/main/java/netneutrality/command/bot/ConfigureCommand.java @@ -16,6 +16,7 @@ import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import netneutrality.command.AbstractCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.command.CommandType; import netneutrality.core.GuildManager; import netneutrality.core.context.MessageCommandContext; @@ -79,7 +80,7 @@ public class ConfigureCommand extends AbstractCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { String[] args = context.getArgs(); GuildManager guildManager = GuildManager.getManager(context.getGuild()); @@ -204,10 +205,12 @@ public class ConfigureCommand extends AbstractCommand { } } } + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { String sub = context.getEvent().getFullCommandName().split(" ")[1]; GuildManager guildManager = GuildManager.getManager(context.getGuild()); context.ackAndWait(true); @@ -218,14 +221,14 @@ public class ConfigureCommand extends AbstractCommand { if (role.getPosition() == -1) { guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_ROLE, null); - context.replyEphemeral("Everyone can now use music commands"); - return; + + return CommandExecutionResult.success("Everyone can now use music commands"); } if (role.getGuild().getId().equals(context.getGuild().getId())) { guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_ROLE, role.getId()); - context.replyEphemeral("Successfully set %s as the role needed for music command", role.getAsMention()); - return; + + return CommandExecutionResult.success(String.format("Successfully set %s as the role needed for music command", role.getAsMention())); } } @@ -234,15 +237,15 @@ public class ConfigureCommand extends AbstractCommand { if (channel == null) { guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_CHANNEL, null); - context.replyEphemeral("No channel restrictions for music commands"); - return; + + return CommandExecutionResult.success("No channel restrictions for music commands"); } if (channel instanceof TextChannel) { if (channel.getGuild().getId().equals(context.getGuild().getId())) { guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_CHANNEL, channel.getId()); - context.replyEphemeral("Successfully set %s as the channel required to execute music command", channel.getAsMention()); - return; + + return CommandExecutionResult.success(String.format("Successfully set %s as the channel required to execute music command", channel.getAsMention())); } } @@ -253,16 +256,14 @@ public class ConfigureCommand extends AbstractCommand { guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_VOLUME, String.valueOf(volume)); MusicManager.get(context.getGuild()).setVolume(volume); - context.replyEphemeral("Default volume for music player is now %d", volume); - return; + return CommandExecutionResult.success(String.format("Default volume for music player is now %d", volume)); } if ("debug".equals(sub)) { boolean debug = context.getEvent().getOption("debug", true, OptionMapping::getAsBoolean); - guildManager.setDebug(debug); - context.reply("Error logging is now %s for this guild", (debug ? "enabled" : "disabled")); - return; + + return CommandExecutionResult.success(String.format("Error logging is now %s for this guild", (debug ? "enabled" : "disabled"))); } if ("show-all".equals(sub)) { @@ -282,5 +283,7 @@ public class ConfigureCommand extends AbstractCommand { context.replyEphemeral(builder.build()); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java b/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java index 63a2e2b..14ec58d 100644 --- a/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java +++ b/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java @@ -9,6 +9,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.command.CommandType; import netneutrality.core.LogHandler; import netneutrality.core.context.MessageCommandContext; @@ -62,7 +63,7 @@ public class CryptoPriceCommand extends AbstractCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { String[] args = context.getArgs(); String currency = "USD"; @@ -71,8 +72,8 @@ public class CryptoPriceCommand extends AbstractCommand { try { currency = Currency.getInstance(args[1].toUpperCase()).getCurrencyCode(); } catch (IllegalArgumentException exception) { - context.reply("Please enter a valid currency"); - return; + + return CommandExecutionResult.warn("Please enter a valid currency"); } } @@ -101,10 +102,12 @@ public class CryptoPriceCommand extends AbstractCommand { } }); } + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { Locale usa = new Locale("en", "US"); NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa); dollarFormat.setMaximumFractionDigits(24); @@ -115,8 +118,7 @@ public class CryptoPriceCommand extends AbstractCommand { try { currency = Currency.getInstance(currency).getCurrencyCode(); } catch (IllegalArgumentException exception) { - context.reply("Please enter a valid currency"); - return; + return CommandExecutionResult.error("Please enter a valid currency"); } String finalCurrency = currency.toUpperCase(); @@ -143,5 +145,7 @@ public class CryptoPriceCommand extends AbstractCommand { }); + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/BitconnectCommand.java b/src/main/java/netneutrality/command/music/BitconnectCommand.java index 6844b1b..e607263 100644 --- a/src/main/java/netneutrality/command/music/BitconnectCommand.java +++ b/src/main/java/netneutrality/command/music/BitconnectCommand.java @@ -8,6 +8,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.command.CommandType; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; @@ -41,19 +42,20 @@ public class BitconnectCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); player.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, false, true); context.deleteMessage(); + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); context.ackAndWait(); player.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, false, true); - context.reply("Ready to invest?"); + return CommandExecutionResult.success("Ready to invest?"); } } diff --git a/src/main/java/netneutrality/command/music/ClearQueueCommand.java b/src/main/java/netneutrality/command/music/ClearQueueCommand.java index 0daf844..da32cdd 100644 --- a/src/main/java/netneutrality/command/music/ClearQueueCommand.java +++ b/src/main/java/netneutrality/command/music/ClearQueueCommand.java @@ -8,6 +8,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -42,11 +43,11 @@ public class ClearQueueCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (!MusicUtils.checkIfConnected(player, context)) - return; + return CommandExecutionResult.none(); if (context.getArgs().length == 0) { context.reply("Select the track you want to delete from the queue (track# or all)"); @@ -70,11 +71,7 @@ public class ClearQueueCommand extends AbstractMusicCommand { int num = Integer.parseInt(context.getArgument(0)); if (num > 0) { - if (player.removeFromQueue(num)) { - context.reply("Removed track #%d from the queue", num); - } else { - context.reply("Error while removing track #%d from the queue", num); - } + return player.getScheduler().getQueueManager().removeFromQueue(num); } else { context.reply("Number out of range"); } @@ -84,22 +81,19 @@ public class ClearQueueCommand extends AbstractMusicCommand { } } } + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); context.ackAndWait(); if (!MusicUtils.checkIfConnected(manager, context)) - return; + return CommandExecutionResult.none(); - int queueSize = manager.getQueueSize(); - if (queueSize > 0) { - manager.getScheduler().getQueueManager().clearQueue(); - context.reply(String.format("Removed %d track%s from the queue", queueSize--, (queueSize > 1 ? "s" : ""))); - } else { - context.reply("Queue is empty!"); - } + return manager.getScheduler().getQueueManager().clearQueue(); } + } diff --git a/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java b/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java index a852a4f..34d24d7 100644 --- a/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java +++ b/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java @@ -8,6 +8,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -37,7 +38,7 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (MusicUtils.checkIfConnected(player, context) && player.isCurrentlyPlaying()) { @@ -46,15 +47,18 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand { context.reply("Bot isn't playing any tracks right now"); } + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); context.ackAndWait(); if (MusicUtils.checkIfConnected(manager, context) && manager.isCurrentlyPlaying()) { context.reply(MessageFunction.buildCurrentlyPlayingMessage(manager)); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/JoinCommand.java b/src/main/java/netneutrality/command/music/JoinCommand.java index 627b3ec..c359e0f 100644 --- a/src/main/java/netneutrality/command/music/JoinCommand.java +++ b/src/main/java/netneutrality/command/music/JoinCommand.java @@ -9,6 +9,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.exceptions.CommandExecutionException; @@ -37,7 +38,7 @@ public class JoinCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (context.getGuildUser().getVoiceState() == null) { @@ -45,13 +46,11 @@ public class JoinCommand extends AbstractMusicCommand { } if (!context.getGuildUser().getVoiceState().inAudioChannel()) { - context.reply("You are not in a voice channel"); - return; + return CommandExecutionResult.warn("You are not in a voice channel"); } if (player.isConnected()) { - context.reply("Player is already in a voice channel"); - return; + return CommandExecutionResult.warn("Player is already in a voice channel"); } VoiceChannel vChannel = (VoiceChannel) context.getGuildUser().getVoiceState().getChannel(); @@ -60,10 +59,11 @@ public class JoinCommand extends AbstractMusicCommand { context.reply("Joining current voice channel"); } + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); context.ackAndWait(); @@ -72,13 +72,11 @@ public class JoinCommand extends AbstractMusicCommand { } if (!context.getGuildUser().getVoiceState().inAudioChannel()) { - context.reply("You are not in a voice channel"); - return; + return CommandExecutionResult.warn("You are not in a voice channel"); } if (player.isConnected()) { - context.reply("Player is already in a voice channel"); - return; + return CommandExecutionResult.warn("Player is already in a voice channel"); } VoiceChannel vChannel = (VoiceChannel) context.getGuildUser().getVoiceState().getChannel(); @@ -86,5 +84,7 @@ public class JoinCommand extends AbstractMusicCommand { player.connect(vChannel); context.reply("Joining current voice channel"); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/LeaveCommand.java b/src/main/java/netneutrality/command/music/LeaveCommand.java index 8b948ce..6a6a318 100644 --- a/src/main/java/netneutrality/command/music/LeaveCommand.java +++ b/src/main/java/netneutrality/command/music/LeaveCommand.java @@ -8,6 +8,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -36,17 +37,19 @@ public class LeaveCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (MusicUtils.checkIfConnected(player, context)) { player.leave(); context.reply("Leaving voice channel and clearing queue"); } + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); context.ackAndWait(); @@ -54,5 +57,7 @@ public class LeaveCommand extends AbstractMusicCommand { player.leave(); context.reply("Leaving voice channel and clearing queue"); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/PlayCommand.java b/src/main/java/netneutrality/command/music/PlayCommand.java index f414c8c..39cf5e8 100644 --- a/src/main/java/netneutrality/command/music/PlayCommand.java +++ b/src/main/java/netneutrality/command/music/PlayCommand.java @@ -10,6 +10,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -37,21 +38,23 @@ public class PlayCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (context.getArgs().length > 0) { player.play(context.getMessageText(), context, false, false); } + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); String query = context.getEvent().getOption("query", OptionMapping::getAsString); context.ackAndWait(); manager.play(query, context, false, false); + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/QueueCommand.java b/src/main/java/netneutrality/command/music/QueueCommand.java index 5615a82..32e5153 100644 --- a/src/main/java/netneutrality/command/music/QueueCommand.java +++ b/src/main/java/netneutrality/command/music/QueueCommand.java @@ -13,6 +13,7 @@ import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -58,11 +59,11 @@ public class QueueCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (!MusicUtils.checkIfConnected(player, context)) - return; + return CommandExecutionResult.none(); if (context.getArgs().length == 0) { context.reply("Select the track you want to delete from the queue (track# or all)"); @@ -86,11 +87,7 @@ public class QueueCommand extends AbstractMusicCommand { int num = Integer.parseInt(context.getArgument(0)); if (num > 0) { - if (player.removeFromQueue(num)) { - context.reply("Removed track #%d from the queue", num); - } else { - context.reply("Error while removing track #%d from the queue", num); - } + return player.getScheduler().getQueueManager().removeFromQueue(num); } else { context.reply("Number out of range"); } @@ -100,47 +97,34 @@ public class QueueCommand extends AbstractMusicCommand { } } } + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); context.ackAndWait(); String sub = context.getEvent().getFullCommandName().split(" ")[1]; if (!MusicUtils.checkIfConnected(manager, context)) { - return; + return CommandExecutionResult.none(); } switch (sub) { case "clear-all" -> { - int queueSize = manager.getQueueSize(); - - if (queueSize > 0) { - manager.getScheduler().getQueueManager().clearQueue(); - context.reply(String.format("Removed %d track%s from the queue", queueSize--, (queueSize > 1 ? "s" : ""))); - } else { - context.reply("Queue is already empty!"); - } + return manager.getScheduler().getQueueManager().clearQueue(); } case "delete-track" -> { int position = context.getEvent().getOption("position", 0, OptionMapping::getAsInt); - - if (position > 0) { - if (manager.removeFromQueue(position)) { - context.reply("Removed track #%d from the queue", position); - } else { - context.reply("Position is out of bounds"); - } - } + return manager.getScheduler().getQueueManager().removeFromQueue(position); } case "show-queue" -> context.reply(MessageFunction.buildViewQueueMessage(manager, true)); case "shuffle" -> { - manager.getScheduler().getQueueManager().shuffle(); - context.reply("Queue is now shuffled."); + return manager.getScheduler().getQueueManager().shuffle(); } case "from-user" -> { @@ -174,6 +158,6 @@ public class QueueCommand extends AbstractMusicCommand { } } - + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/ShuffleCommand.java b/src/main/java/netneutrality/command/music/ShuffleCommand.java index a5ee873..22c3623 100644 --- a/src/main/java/netneutrality/command/music/ShuffleCommand.java +++ b/src/main/java/netneutrality/command/music/ShuffleCommand.java @@ -8,6 +8,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; import netneutrality.utils.MusicUtils; @@ -34,13 +35,14 @@ public class ShuffleCommand extends AbstractMusicCommand { } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); context.ackAndWait(); if (MusicUtils.checkIfConnected(manager, context)) { - manager.getScheduler().getQueueManager().shuffle(); - context.reply("Queue is now shuffled."); + return manager.getScheduler().getQueueManager().shuffle(); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/SkipCommand.java b/src/main/java/netneutrality/command/music/SkipCommand.java index e52642c..6133ae4 100644 --- a/src/main/java/netneutrality/command/music/SkipCommand.java +++ b/src/main/java/netneutrality/command/music/SkipCommand.java @@ -11,6 +11,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -41,11 +42,11 @@ public class SkipCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (!MusicUtils.checkIfConnected(player, context)) - return; + return CommandExecutionResult.none(); if (UserFunction.isAdmin(context.getGuildUser()) || MusicUtils.isUserDj(context.getGuildUser())) { if (UserFunction.isAdmin(context.getGuildUser()) && context.getArgs().length > 0) { @@ -65,22 +66,19 @@ public class SkipCommand extends AbstractMusicCommand { player.voteSkip(context); } + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); - int skips = context.getEvent().getOption("skip", 0, OptionMapping::getAsInt); + int skips = context.getEvent().getOption("skip", 1, OptionMapping::getAsInt); context.ackAndWait(); if (MusicUtils.checkIfConnected(manager, context)) { - if (skips > 0) { - context.reply("Skipping %s track%s", skips, (skips > 1 ? "s" : "")); - manager.getScheduler().getQueueManager().skip(skips); - } else { - context.reply("Skipping current track"); - manager.getScheduler().getQueueManager().skip(1); - } + return manager.getScheduler().getQueueManager().skip(skips); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/StopCommand.java b/src/main/java/netneutrality/command/music/StopCommand.java index 3a87054..49c5928 100644 --- a/src/main/java/netneutrality/command/music/StopCommand.java +++ b/src/main/java/netneutrality/command/music/StopCommand.java @@ -8,6 +8,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -37,28 +38,31 @@ public class StopCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (!MusicUtils.checkIfConnected(player, context)) - return; + return CommandExecutionResult.none(); // Need a resume command before - // if (UserFunction.isAdmin(context.getGuildUser()) || MusicUtils.isUserDj(context.getGuildUser())) { if (UserFunction.isAdmin(context.getGuildUser())) { player.stopTrack(); context.reply("Stopping current track"); } + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); context.ackAndWait(); if (MusicUtils.checkIfConnected(manager, context)) { manager.stopTrack(); - context.reply("Stopping music playback"); + return CommandExecutionResult.success("Stopping music playback"); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/ViewQueueCommand.java b/src/main/java/netneutrality/command/music/ViewQueueCommand.java index 58a568f..d2c2ace 100644 --- a/src/main/java/netneutrality/command/music/ViewQueueCommand.java +++ b/src/main/java/netneutrality/command/music/ViewQueueCommand.java @@ -7,6 +7,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -36,7 +37,7 @@ public class ViewQueueCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (MusicUtils.checkIfConnected(player, context)) { @@ -48,10 +49,11 @@ public class ViewQueueCommand extends AbstractMusicCommand { } } + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); context.ackAndWait(); @@ -61,8 +63,10 @@ public class ViewQueueCommand extends AbstractMusicCommand { if (queueSize > 0) { context.reply(MessageFunction.buildViewQueueMessage(manager, true)); } else { - context.reply("Queue is empty!"); + return CommandExecutionResult.warn("Queue is empty!"); } } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/VolumeCommand.java b/src/main/java/netneutrality/command/music/VolumeCommand.java index 0943481..ec69272 100644 --- a/src/main/java/netneutrality/command/music/VolumeCommand.java +++ b/src/main/java/netneutrality/command/music/VolumeCommand.java @@ -11,6 +11,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -41,11 +42,11 @@ public class VolumeCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); if (!MusicUtils.checkIfConnected(player, context)) - return; + return CommandExecutionResult.none(); if (UserFunction.isAdmin(context.getGuildUser()) || MusicUtils.isUserDj(context.getGuildUser())) { try { @@ -61,16 +62,20 @@ public class VolumeCommand extends AbstractMusicCommand { context.reply("Please enter a value from 0 to 100"); } } + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); int volume = context.getEvent().getOption("volume", 30, OptionMapping::getAsInt); if (MusicUtils.checkIfConnected(manager, context)) { - context.reply("Volume set to %s", volume); manager.setVolume(volume); + return CommandExecutionResult.success(String.format("Volume set to %s", volume)); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/command/music/VoteSkipCommand.java b/src/main/java/netneutrality/command/music/VoteSkipCommand.java index ef29123..f07c358 100644 --- a/src/main/java/netneutrality/command/music/VoteSkipCommand.java +++ b/src/main/java/netneutrality/command/music/VoteSkipCommand.java @@ -7,6 +7,7 @@ package netneutrality.command.music; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import netneutrality.command.AbstractMusicCommand; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.context.MessageCommandContext; import netneutrality.core.context.SlashCommandContext; import netneutrality.music.MusicManager; @@ -35,20 +36,24 @@ public class VoteSkipCommand extends AbstractMusicCommand { } @Override - public void execute(MessageCommandContext context) { + public CommandExecutionResult execute(MessageCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); if (MusicUtils.checkIfConnected(manager, context)) { manager.voteSkip(context); } + + return CommandExecutionResult.none(); } @Override - public void execute(SlashCommandContext context) { + public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); if (MusicUtils.checkIfConnected(manager, context)) { - manager.voteSkip(context); + return manager.voteSkip(context); } + + return CommandExecutionResult.none(); } } diff --git a/src/main/java/netneutrality/core/CommandProcessor.java b/src/main/java/netneutrality/core/CommandProcessor.java new file mode 100644 index 0000000..0c31320 --- /dev/null +++ b/src/main/java/netneutrality/core/CommandProcessor.java @@ -0,0 +1,111 @@ +package netneutrality.core; +/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +import io.sentry.Sentry; +import netneutrality.command.AbstractCommand; +import netneutrality.command.CommandExecutionResult; +import netneutrality.command.CommandManager; +import netneutrality.core.context.CommandContext; +import netneutrality.core.context.MessageCommandContext; +import netneutrality.core.context.SlashCommandContext; +import netneutrality.exceptions.CommandExecutionException; +import netneutrality.utils.UserFunction; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import static netneutrality.command.CommandExecutionResult.Result.*; + +public class CommandProcessor { + + private final static Logger logger = LogManager.getLogger(CommandProcessor.class); + private final String commandName; + private final CommandContext context; + + public CommandProcessor(String commandName, CommandContext context) { + this.commandName = commandName; + this.context = context; + } + + public void dispatch() { + + if (!CommandManager.isValidCommand(commandName)) { + return; + } + + AbstractCommand command = CommandManager.getCommand(commandName); + logger.info("Executing command {} on guild {}", command.getCommandName(), context.getGuild().getId()); + + if (context instanceof SlashCommandContext slashCommandContext) + logger.debug("SlashCommandInteractionId: {}", slashCommandContext.getEvent().getInteraction().getId()); + + configureSentry(command); + + try { + + if (context instanceof MessageCommandContext && command.needAdmin() && !UserFunction.isAdmin(context.getGuildUser())) { + context.reply("You are not powerful enough, scrub"); + return; + } + + if (command.canBeExecutedBy(context.getGuild(), context.getGuildUser())) { + if (command.canBeExecutedFrom(context.getGuild(), context.getChannel())) { + CommandExecutionResult commandExecutionResult = null; + + if (context instanceof SlashCommandContext slashCommandContext) { + commandExecutionResult = command.execute(slashCommandContext); + } + + if (context instanceof MessageCommandContext messageCommandContext) { + commandExecutionResult = command.execute(messageCommandContext); + } + + if (commandExecutionResult == null) { + throw new RuntimeException("Command type is not implemented."); + } + + CommandExecutionResult.Result result = commandExecutionResult.getResult(); + String message = commandExecutionResult.getMessage(); + if (result == NOACTION) { + return; + } + + if (result == ERROR) { + Exception exception = commandExecutionResult.getException(); + + logger.error("Error from command {}: {}", command.getCommandName(), message, exception); + } + + context.reply(message); + } + } + + //TODO: make better + } catch (CommandExecutionException exception) { + LogHandler.log(exception); + } catch (Exception exception) { + LogHandler.log(new CommandExecutionException("Error during command execution", context, exception)); + } + } + + private void configureSentry(AbstractCommand command) { + + Sentry.configureScope(scope -> { + scope.setContexts("command", command.getCommandName()); + scope.setContexts("isAdmin", UserFunction.isAdmin(context.getGuildUser())); + scope.setContexts("canBeExecuted", command.canBeExecutedBy(context.getGuild(), context.getGuildUser())); + scope.setTag("channel", context.getChannel().getId()); + + if (context instanceof SlashCommandContext slashCommandContext) + scope.setTag("interactionId", slashCommandContext.getEvent().getInteraction().getId()); + + if (context instanceof MessageCommandContext messageCommandContext) + scope.setTag("message", messageCommandContext.getMessage().getId()); + + scope.setTag("guild", context.getGuild().getId()); + }); + } +} diff --git a/src/main/java/netneutrality/core/context/CommandContext.java b/src/main/java/netneutrality/core/context/CommandContext.java index bd8e580..c812826 100644 --- a/src/main/java/netneutrality/core/context/CommandContext.java +++ b/src/main/java/netneutrality/core/context/CommandContext.java @@ -57,6 +57,4 @@ public interface CommandContext { default void replyToMessage(MessageEmbed... embeds) { replyToMessage(MessageCreateData.fromEmbeds(embeds)); } - - void dispatchToCommand(String commandName); } diff --git a/src/main/java/netneutrality/core/context/MessageCommandContext.java b/src/main/java/netneutrality/core/context/MessageCommandContext.java index 595d2e0..2906077 100644 --- a/src/main/java/netneutrality/core/context/MessageCommandContext.java +++ b/src/main/java/netneutrality/core/context/MessageCommandContext.java @@ -13,13 +13,9 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.utils.messages.MessageCreateData; import netneutrality.command.AbstractCommand; -import netneutrality.core.CommandManager; import netneutrality.core.GuildManager; -import netneutrality.core.LogHandler; -import netneutrality.exceptions.CommandExecutionException; import netneutrality.thread.ThreadManager; import netneutrality.utils.Settings; -import netneutrality.utils.UserFunction; import java.util.Collection; import java.util.concurrent.ExecutorService; @@ -193,39 +189,4 @@ public class MessageCommandContext implements CommandContext { return creatorId.equals(member.getId()); } - public void dispatchToCommand(String commandName) { - if (!CommandManager.isValidCommand(commandName)) { - return; - } - - AbstractCommand command = CommandManager.getCommand(commandName); - this.command = command; - //TODO: Add usage check - - Sentry.configureScope(scope -> { - scope.setContexts("command", command.getCommandName()); - scope.setContexts("isAdmin", UserFunction.isAdmin(member)); - scope.setContexts("canBeExecuted", command.canBeExecutedBy(guild, member)); - scope.setTag("channel", channel.getId()); - scope.setTag("message", message.getId()); - scope.setTag("guild", guild.getId()); - }); - - try { - if (command.needAdmin() && !UserFunction.isAdmin(member)) { - reply("You are not powerful enough, scrub"); - return; - } - - if (command.canBeExecutedBy(guild, member)) { - if (command.canBeExecutedFrom(guild, channel)) { - command.execute(this); - } - } - } catch (CommandExecutionException e) { - LogHandler.log(e); - } catch (Exception e) { - LogHandler.log(new CommandExecutionException("Error during command execution", this, e)); - } - } } diff --git a/src/main/java/netneutrality/core/context/SlashCommandContext.java b/src/main/java/netneutrality/core/context/SlashCommandContext.java index 352efa3..e46a880 100644 --- a/src/main/java/netneutrality/core/context/SlashCommandContext.java +++ b/src/main/java/netneutrality/core/context/SlashCommandContext.java @@ -1,12 +1,10 @@ package netneutrality.core.context; - /* * Copyright (c) anthorob * * https://discord.gg/qUa6zNFZsd */ -import io.sentry.Sentry; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; @@ -19,9 +17,6 @@ import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.api.utils.messages.MessageEditData; import netneutrality.command.AbstractCommand; -import netneutrality.core.CommandManager; -import netneutrality.core.LogHandler; -import netneutrality.exceptions.CommandExecutionException; import java.util.Collection; @@ -174,32 +169,12 @@ public class SlashCommandContext implements CommandContext { ackAndWait(false); } - public void dispatchToCommand(String commandName) { - if (!CommandManager.isValidCommand(commandName)) { - return; - } - - AbstractCommand command = CommandManager.getCommand(commandName); - this.command = command; - - Sentry.configureScope(scope -> { - scope.setContexts("command", command.getCommandName()); - scope.setContexts("canBeExecuted", command.canBeExecutedBy(guild, member)); - scope.setTag("channel", channel.getId()); - scope.setTag("interactionId", event.getInteraction().getId()); - scope.setTag("guild", guild.getId()); - }); - - try { - if (command.canBeExecutedBy(guild, member)) { - command.execute(this); - } - - } catch (CommandExecutionException exception) { - LogHandler.log(exception); - } catch (Exception exception) { - LogHandler.log(new CommandExecutionException("Error during command execution", this, exception)); - } - + public void ack() { + ackAndWait(); } + + public void ephemeral() { + ackAndWait(true); + } + } diff --git a/src/main/java/netneutrality/hooks/SlashCommandHooks.java b/src/main/java/netneutrality/hooks/SlashCommandHooks.java index 6c6e809..6e5d99b 100644 --- a/src/main/java/netneutrality/hooks/SlashCommandHooks.java +++ b/src/main/java/netneutrality/hooks/SlashCommandHooks.java @@ -7,6 +7,7 @@ package netneutrality.hooks; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import netneutrality.core.CommandProcessor; import netneutrality.core.context.SlashCommandContext; import org.jetbrains.annotations.NotNull; @@ -17,6 +18,8 @@ public class SlashCommandHooks extends ListenerAdapter { String commandName = event.getName(); SlashCommandContext commandContext = SlashCommandContext.createContext(event); - commandContext.dispatchToCommand(commandName); + CommandProcessor processor = new CommandProcessor(commandName, commandContext); + processor.dispatch(); + } } diff --git a/src/main/java/netneutrality/hooks/message/MessageReceivedHandler.java b/src/main/java/netneutrality/hooks/message/MessageReceivedHandler.java index c1935ea..f7a87c8 100644 --- a/src/main/java/netneutrality/hooks/message/MessageReceivedHandler.java +++ b/src/main/java/netneutrality/hooks/message/MessageReceivedHandler.java @@ -10,6 +10,7 @@ import io.sentry.Sentry; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import netneutrality.core.CommandProcessor; import netneutrality.core.GuildManager; import netneutrality.core.context.MessageCommandContext; import netneutrality.utils.Settings; @@ -28,7 +29,6 @@ public class MessageReceivedHandler extends ListenerAdapter { Message message = event.getMessage(); MessageCommandContext context = MessageCommandContext.createContext(event); - Sentry.addBreadcrumb(Breadcrumb.info("New message from " + context.getGuildUser().getEffectiveName())); GuildManager.getManager(context.getGuild()).checkAndLogMessage(message, context.getGuildUser(), context.getChannel()); @@ -40,7 +40,8 @@ public class MessageReceivedHandler extends ListenerAdapter { // rawMessage = rawMessage.substring(prefix.length()).trim(); String commandString = rawMessage.split(" ", 2)[0]; - context.dispatchToCommand(commandString); + CommandProcessor processor = new CommandProcessor(commandString, context); + processor.dispatch(); } } } diff --git a/src/main/java/netneutrality/music/MusicManager.java b/src/main/java/netneutrality/music/MusicManager.java index b6c07ce..d096bc7 100644 --- a/src/main/java/netneutrality/music/MusicManager.java +++ b/src/main/java/netneutrality/music/MusicManager.java @@ -17,6 +17,7 @@ import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import netneutrality.command.CommandExecutionResult; import netneutrality.core.GuildManager; import netneutrality.core.LogHandler; import netneutrality.core.context.CommandContext; @@ -152,7 +153,7 @@ public class MusicManager { } public synchronized void play(String url, CommandContext context, boolean needToBeConnected, boolean silent) { - logger.debug("Guild {}: request to play {} by user {}", guild.getId(), url, context.getGuildUser().getId()); + logger.debug("Guild {}: request to play '{}' by user {}", guild.getId(), url, context.getGuildUser().getId()); List toLoad = new ArrayList<>(); toLoad.add(new LoadableSong(null, url, null)); @@ -194,24 +195,24 @@ public class MusicManager { loader.loadAllSongs(songs); } - public synchronized boolean removeFromQueue(int index) { - return scheduler.getQueueManager().removeFromQueue(index); - } - public synchronized void stopTrack() { player.stopTrack(); } - public synchronized void voteSkip(CommandContext context) { + public synchronized CommandExecutionResult voteSkip(CommandContext context) { VoiceChannel voiceChannel = (VoiceChannel) guild.getAudioManager().getConnectedChannel(); - QueueManager.TrackInfo info = scheduler.getQueueManager().peekHeadOfQueue(); - if (!isCurrentlyPlaying() || voiceChannel == null) { - return; + if (voiceChannel == null) { + return CommandExecutionResult.none(); } + if (!isCurrentlyPlaying()) { + return CommandExecutionResult.none(); + } + + QueueManager.TrackInfo info = scheduler.getQueueManager().peekHeadOfQueue(); if (info == null) { - return; + return CommandExecutionResult.none(); } // Minus the bot itself @@ -219,9 +220,9 @@ public class MusicManager { if (connected < 3) { context.reply("Skipping current track since not enough people are connected to the voice channel."); - scheduler.getQueueManager().skip(1); + scheduler.getQueueManager().skip(); - return; + return CommandExecutionResult.none(); } double needed = connected / 2.1; @@ -230,11 +231,12 @@ public class MusicManager { logger.debug("VoteSkip: guild={}, connected={}, needed={}, skips={}, user={}", context.getGuild().getId(), connected, needed, info.getSkips().size(), context.getGuildUser().getId()); if (info.getSkips().size() > needed) { - context.reply("Skipping current track: %s", info.getTrack().getInfo().title); - scheduler.getQueueManager().skip(1); + return scheduler.getQueueManager().skip(); } else { context.reply("Adding your vote to skip the current track. Current votes: %d/%d", info.getSkips().size(), (int) Math.ceil(needed)); } + + return CommandExecutionResult.none(); } public synchronized void setVolume(int volume) { diff --git a/src/main/java/netneutrality/music/QueueManager.java b/src/main/java/netneutrality/music/QueueManager.java index d6bab24..70c0d1e 100644 --- a/src/main/java/netneutrality/music/QueueManager.java +++ b/src/main/java/netneutrality/music/QueueManager.java @@ -9,6 +9,7 @@ import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; +import netneutrality.command.CommandExecutionResult; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -136,12 +137,22 @@ public class QueueManager { } } - public void clearQueue() { + public CommandExecutionResult clearQueue() { scheduler.getMusicManager().stopLoading(); scheduler.getMusicManager().leave(); + if (queue.isEmpty()) { + return CommandExecutionResult.warn("Queue is empty!"); + } + synchronized (queue) { + int queueSize = queue.size(); + if (queueSize == 0) { + return CommandExecutionResult.warn("Queue is empty!"); + } + queue.clear(); + return CommandExecutionResult.success(String.format("Removed %d track%s from the queue", queueSize--, (queueSize > 1 ? "s" : ""))); } } @@ -210,19 +221,19 @@ public class QueueManager { } } - public void skip() { - skip(1); + public CommandExecutionResult skip() { + return skip(1); } - public void skip(int nbTrack) { - if (nbTrack == 0) - return; + public CommandExecutionResult skip(int nbTrack) { + if (nbTrack == 0) { + nbTrack = 1; + } synchronized (queue) { - if (queue.isEmpty()) { scheduler.getMusicManager().leave(); - return; + return CommandExecutionResult.info("Queue is empty, leaving voice channel"); } if (nbTrack > queue.size()) { @@ -234,11 +245,22 @@ public class QueueManager { queue.poll(); } + if (queue.isEmpty()) { + scheduler.getMusicManager().leave(); + return CommandExecutionResult.info("Queue is empty, leaving voice channel"); + } + startNextTrack(); + + return CommandExecutionResult.success(String.format("Skipping %s track%s..", nbTrack, (nbTrack > 1 ? "s" : ""))); } } - public void shuffle() { + public CommandExecutionResult shuffle() { + if (queue.size() > 3) { + return CommandExecutionResult.none(); + } + synchronized (queue) { if (queue.size() > 3) { logger.debug("Guild {}: shuffling queue", guild.getId()); @@ -251,29 +273,43 @@ public class QueueManager { queue.clear(); queue.add(current); queue.addAll(newQueue); + + return CommandExecutionResult.success("Queue is now shuffled."); } + + return CommandExecutionResult.none(); } } - public boolean removeFromQueue(int index) { + public CommandExecutionResult removeFromQueue(int index) { + if (queue.isEmpty() || index < 1) { + return CommandExecutionResult.none(); + } + synchronized (queue) { - if (queue.size() > 0 && index <= queue.size()) { - logger.debug("Guild {}: removing index {} from queue", guild.getId(), index - 1); + if (queue.isEmpty()) { + return CommandExecutionResult.none(); + } - if (index == 1) { - skip(1); - return true; - } + if (index > queue.size()) { + return CommandExecutionResult.error("Position is out of bounds"); + } + logger.debug("Guild {}: removing index {} from queue", guild.getId(), index - 1); + + if (index > 1) { List newQueue = new ArrayList<>(queue); newQueue.remove(index - 1); queue.clear(); queue.addAll(newQueue); - return true; + + return CommandExecutionResult.success(String.format("Removed track #%d from the queue", index)); } - return false; + skip(); + return CommandExecutionResult.none(); + } } diff --git a/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java b/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java index b0b5b5a..d367442 100644 --- a/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java +++ b/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java @@ -11,12 +11,14 @@ import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel; import netneutrality.NetNeutrality; import netneutrality.music.MusicManager; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.util.List; public class MusicPlayerAutoDisconnectThread implements Runnable { - final MusicManager manager; + private final Logger logger = LogManager.getLogger(MusicPlayerAutoDisconnectThread.class); + private final MusicManager manager; //TODO: move to scheduler public MusicPlayerAutoDisconnectThread(MusicManager musicManager) { @@ -35,7 +37,7 @@ public class MusicPlayerAutoDisconnectThread implements Runnable { Thread.sleep(30000); if (conditionsMetToDisconnect(channel)) { - LogManager.getLogger(MusicPlayerAutoDisconnectThread.class).debug("Guild {}: auto-disconnect player from voice channel: {}", guild.getId(), channel.getId()); + logger.debug("Guild {}: auto-disconnect player from voice channel: {}", guild.getId(), channel.getId()); manager.leave(); } } @@ -48,6 +50,6 @@ public class MusicPlayerAutoDisconnectThread implements Runnable { private boolean conditionsMetToDisconnect(VoiceChannel channel) { List members = channel.getMembers().stream().filter(member -> !member.getId().equals(NetNeutrality.getSelf().getId())).toList(); - return members.size() == 0 || manager.getScheduler().getQueueManager().isEmpty(); + return members.isEmpty() || manager.getScheduler().getQueueManager().isEmpty(); } } diff --git a/src/main/java/netneutrality/utils/MessageFunction.java b/src/main/java/netneutrality/utils/MessageFunction.java index 91c16fa..72fcc92 100644 --- a/src/main/java/netneutrality/utils/MessageFunction.java +++ b/src/main/java/netneutrality/utils/MessageFunction.java @@ -17,7 +17,7 @@ import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import netneutrality.command.AbstractCommand; import netneutrality.command.CommandType; -import netneutrality.core.CommandManager; +import netneutrality.command.CommandManager; import netneutrality.core.context.CommandContext; import netneutrality.exceptions.CommandException; import netneutrality.music.MusicManager;