diff --git a/src/main/java/me/bobert/netneutrality/command/CommandType.java b/src/main/java/me/bobert/netneutrality/command/CommandType.java index 340993e..95bc4da 100644 --- a/src/main/java/me/bobert/netneutrality/command/CommandType.java +++ b/src/main/java/me/bobert/netneutrality/command/CommandType.java @@ -23,4 +23,9 @@ public enum CommandType { public int getId() { return id; } + + @Override + public String toString() { + return description; + } } diff --git a/src/main/java/me/bobert/netneutrality/command/basic/HelpCommand.java b/src/main/java/me/bobert/netneutrality/command/basic/HelpCommand.java index 39ee2c3..3345f59 100644 --- a/src/main/java/me/bobert/netneutrality/command/basic/HelpCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/basic/HelpCommand.java @@ -6,13 +6,23 @@ package me.bobert.netneutrality.command.basic; */ import me.bobert.netneutrality.command.AbstractCommand; +import me.bobert.netneutrality.command.Command; import me.bobert.netneutrality.command.CommandType; import me.bobert.netneutrality.context.MessageCommandContext; import me.bobert.netneutrality.context.SlashCommandContext; import me.bobert.netneutrality.core.command.CommandExecutionResult; +import me.bobert.netneutrality.core.command.CommandManager; +import me.bobert.netneutrality.core.context.Context; +import me.bobert.netneutrality.core.tasks.BuiltInTask; +import me.bobert.netneutrality.tasks.help.BotInfo; +import me.bobert.netneutrality.tasks.help.CommandHelp; +import me.bobert.netneutrality.tasks.help.ReportBug; import me.bobert.netneutrality.utils.MessageFunction; -import net.dv8tion.jda.api.entities.MessageEmbed; +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 net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import java.util.List; @@ -47,6 +57,7 @@ public class HelpCommand extends AbstractCommand { @Override public void registerSlashCommandOptions(SlashCommandData data) { + data.addOption(OptionType.STRING, "command", "The name of the command you want help with", false); } @Override @@ -56,21 +67,36 @@ public class HelpCommand extends AbstractCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - if (context.getArgs().length == 0) { - List help = MessageFunction.buildHelpMessage(); - - context.reply(new MessageCreateBuilder().addContent(context.getDiscordUser().getAsMention()).addContent(" help has been sent your way!").build()); - context.sendMessageInPrivate(help); - } + context.reply(new MessageCreateBuilder().addContent(context.getDiscordUser().getAsMention()).addContent(" help has been sent your way!").build()); + sendHelp(context, context.getArgument(0)); return CommandExecutionResult.none(); } @Override public CommandExecutionResult execute(SlashCommandContext context) { - List help = MessageFunction.buildHelpMessage(); + sendHelp(context, context.getEvent().getOption("command", null, OptionMapping::getAsString)); - context.sendMessageInPrivate(help); return CommandExecutionResult.success("Help has been sent in DM!"); } + + public void sendHelp(Context context, String commandStr) { + if (commandStr == null) { + Button commands = BuiltInTask.createButton(CommandHelp.class).primary("Commands"); + Button info = BuiltInTask.createButton(BotInfo.class).primary("Info"); + Button reportbug = BuiltInTask.createButton(ReportBug.class).danger("Report bug"); + ActionRow row = ActionRow.of(commands, info, reportbug); + context.sendMessageInPrivate("Thanks for using the Net Neutrality Bot! What do you need help with?", List.of(row)); + return; + } + + Command command = CommandManager.getCommand(commandStr); + if (command == null) { + context.reply("Command does not exist"); + return; + } + + context.reply(MessageFunction.buildCommandHelpMessage(command)); + } + } diff --git a/src/main/java/me/bobert/netneutrality/command/basic/PingCommand.java b/src/main/java/me/bobert/netneutrality/command/basic/PingCommand.java index 5dc94dc..b84210d 100644 --- a/src/main/java/me/bobert/netneutrality/command/basic/PingCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/basic/PingCommand.java @@ -51,7 +51,7 @@ public class PingCommand extends AbstractCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - if (context.getArgs().length == 0) + if (context.getArgs().isEmpty()) context.reply(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing())); return CommandExecutionResult.none(); diff --git a/src/main/java/me/bobert/netneutrality/command/bot/ConfigureCommand.java b/src/main/java/me/bobert/netneutrality/command/bot/ConfigureCommand.java index 22c2af5..a1852b6 100644 --- a/src/main/java/me/bobert/netneutrality/command/bot/ConfigureCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/bot/ConfigureCommand.java @@ -64,14 +64,14 @@ public class ConfigureCommand extends AbstractAdminCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - String[] args = context.getArgs(); + Map args = context.getArgs(); GuildManager guildManager = GuildManager.getManager(context.getGuild()); - if (args.length > 0) { + if (!args.isEmpty()) { // Role for music commands if (context.getArgument(0).equals("music-role")) { - if (args.length == 1) { + if (args.size() == 1) { String roleDb = guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_ROLE); Role role = null; if (!roleDb.isEmpty()) { @@ -82,7 +82,7 @@ public class ConfigureCommand extends AbstractAdminCommand { context.reply("Reset role using 'conf music-role reset' or set it using 'conf musicrole @'"); } - if (args.length == 2) { + if (args.size() == 2) { if (context.getArgument(1).equals("reset")) { if (!guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_ROLE).isEmpty()) { guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_ROLE, null); @@ -104,7 +104,7 @@ public class ConfigureCommand extends AbstractAdminCommand { // Role for music commands if (context.getArgument(0).equals("music-channel")) { - if (args.length == 1) { + if (args.size() == 1) { String channelDb = guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_CHANNEL); TextChannel channel = null; if (!channelDb.isEmpty()) { @@ -115,7 +115,7 @@ public class ConfigureCommand extends AbstractAdminCommand { context.reply("Reset channel using 'conf music-channel reset' or set it using 'conf music-channel #'"); } - if (args.length == 2) { + if (args.size() == 2) { if (context.getArgument(1).equals("reset")) { if (!guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_CHANNEL).isEmpty()) { guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_CHANNEL, null); @@ -137,16 +137,16 @@ public class ConfigureCommand extends AbstractAdminCommand { // Default volume for music player if (context.getArgument(0).equals("music-volume")) { - if (args.length == 1) { + if (args.size() == 1) { int volume = Integer.parseInt(guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_VOLUME)); context.reply("Default volume for music player: %d", volume); context.reply("Set using 'conf music-volume '"); } - if (args.length == 2) { + if (args.size() == 2) { try { - int volume = Integer.parseInt(args[1]); + int volume = Integer.parseInt(args.get(1)); if (volume > 0 && volume <= 100) { guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_VOLUME, String.valueOf(volume)); @@ -164,15 +164,15 @@ public class ConfigureCommand extends AbstractAdminCommand { // Debug if (context.getArgument(0).equals("debug")) { - if (args.length == 1) { + if (args.size() == 1) { boolean debug = guildManager.isDebugEnabled(); context.reply("Error logging is currently %s for this guild.", (debug ? "enabled" : "disabled")); context.reply("Use 'conf debug 0/1' to toggle between states (0 = disabled, 1 = enabled)."); } - if (args.length == 2) { - String str = args[1]; + if (args.size() == 2) { + String str = args.get(1); boolean debug = guildManager.isDebugEnabled(); if (str.equals("0") || str.equalsIgnoreCase("disable")) { debug = false; diff --git a/src/main/java/me/bobert/netneutrality/command/crypto/CryptoPriceCommand.java b/src/main/java/me/bobert/netneutrality/command/crypto/CryptoPriceCommand.java index fd8f74b..194828c 100644 --- a/src/main/java/me/bobert/netneutrality/command/crypto/CryptoPriceCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/crypto/CryptoPriceCommand.java @@ -21,6 +21,7 @@ import org.json.JSONObject; import java.text.NumberFormat; import java.util.Currency; import java.util.Locale; +import java.util.Map; public class CryptoPriceCommand extends AbstractCommand { @@ -59,27 +60,27 @@ public class CryptoPriceCommand extends AbstractCommand { @Override public CommandType getType() { - return CommandType.CRYPTO; + return CommandType.UTILITY; } @Override public CommandExecutionResult execute(MessageCommandContext context) { - String[] args = context.getArgs(); + Map args = context.getArgs(); String currency = "USD"; - if (args.length == 0) { + if (args.isEmpty()) { return CommandExecutionResult.warn("Usage: crypto "); } - if (args.length == 2) { + if (args.size() == 2) { try { - currency = Currency.getInstance(args[1].toUpperCase()).getCurrencyCode(); + currency = Currency.getInstance(args.get(1).toUpperCase()).getCurrencyCode(); } catch (IllegalArgumentException exception) { return CommandExecutionResult.warn("Please enter a valid currency"); } } - String crypto = args[0].toUpperCase(); + String crypto = args.get(0).toUpperCase(); String finalCurrency = currency; context.async("Retreiving price, please wait...", asyncMessage -> { diff --git a/src/main/java/me/bobert/netneutrality/command/music/PlayCommand.java b/src/main/java/me/bobert/netneutrality/command/music/PlayCommand.java index be480cd..d22c3e4 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/PlayCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/PlayCommand.java @@ -41,7 +41,7 @@ public class PlayCommand extends AbstractMusicCommand { public CommandExecutionResult execute(MessageCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); - if (context.getArgs().length == 0) { + if (context.getArgs().isEmpty()) { return CommandExecutionResult.warn("Please specify a query"); } diff --git a/src/main/java/me/bobert/netneutrality/command/music/SkipCommand.java b/src/main/java/me/bobert/netneutrality/command/music/SkipCommand.java index 2aa901f..1bf7443 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/SkipCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/SkipCommand.java @@ -50,7 +50,7 @@ public class SkipCommand extends AbstractMusicCommand { } if (UserFunction.isAdmin(context.getGuildUser()) || MusicUtils.isUserDj(context.getGuildUser())) { - if (UserFunction.isAdmin(context.getGuildUser()) && context.getArgs().length > 0) { + if (UserFunction.isAdmin(context.getGuildUser()) && !context.getArgs().isEmpty()) { try { int skips = Integer.parseInt(context.getArgument(0)); return manager.getQueueManager().skip(skips); diff --git a/src/main/java/me/bobert/netneutrality/context/AsyncContext.java b/src/main/java/me/bobert/netneutrality/context/AsyncContext.java index 25dfdea..056c9de 100644 --- a/src/main/java/me/bobert/netneutrality/context/AsyncContext.java +++ b/src/main/java/me/bobert/netneutrality/context/AsyncContext.java @@ -28,7 +28,7 @@ public class AsyncContext extends AbstractContext { } public AsyncContext(Message message) { - super(message.getJDA(), message.getGuild(), message.getChannel(), message.getMember(), message.getAuthor()); + super(message.getJDA(), message.isFromGuild() ? message.getGuild() : null, message.getChannel(), message.getMember(), message.getAuthor()); this.hook = null; this.message = message; } diff --git a/src/main/java/me/bobert/netneutrality/context/MessageCommandContext.java b/src/main/java/me/bobert/netneutrality/context/MessageCommandContext.java index bf8d75a..f59e823 100644 --- a/src/main/java/me/bobert/netneutrality/context/MessageCommandContext.java +++ b/src/main/java/me/bobert/netneutrality/context/MessageCommandContext.java @@ -14,7 +14,9 @@ import net.dv8tion.jda.api.interactions.components.LayoutComponent; import net.dv8tion.jda.api.interactions.modals.Modal; import net.dv8tion.jda.api.utils.messages.MessageCreateData; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -23,7 +25,7 @@ public class MessageCommandContext extends CommandContext { private final Message message; public MessageCommandContext(MessageReceivedEvent event) { - super(event.getJDA(), event.getGuild(), event.getChannel(), event.getMember(), event.getAuthor()); + super(event.getJDA(), event.isFromGuild() ? event.getGuild() : null, event.getChannel(), event.getMember(), event.getAuthor()); this.event = event; this.message = event.getMessage(); } @@ -34,24 +36,31 @@ public class MessageCommandContext extends CommandContext { } public String getArgument(int index) { - return getArgs()[index]; + return getArgs().get(index); } - public String[] getArgs() { - String msg = message.getContentDisplay().trim(); - msg = msg.substring(Settings.getInstance().get("NETNEUTRALITY_BOT_PREFIX", "$").length()).trim(); - String cmd = msg.split(" ", 2)[0]; - String[] args = msg.replaceFirst("(" + cmd + ")(\\s+)?", "").split(" "); + public Map getArgs() { + Map args = new HashMap<>(); - if (args.length == 1 && args[0].isEmpty()) - args = new String[0]; + String msg = message.getContentDisplay().trim(); + msg = msg.substring(Settings.getInstance().getPrefix().length()).trim(); + String cmd = msg.split(" ", 2)[0]; + + String[] array = msg.replaceFirst("(" + cmd + ")(\\s+)?", "").split(" "); + for (int i = 0; i < array.length; i++) { + args.put(i, array[i]); + } + + if (args.size() == 1 && args.get(0).isEmpty()) { + args.remove(0); + } return args; } public String getMessageText() { String msg = message.getContentDisplay().trim(); - msg = msg.substring(Settings.getInstance().get("NETNEUTRALITY_BOT_PREFIX", "$").length()).trim(); + msg = msg.substring(Settings.getInstance().getPrefix().length()).trim(); String cmd = msg.split(" ", 2)[0]; return msg.replaceFirst("(" + cmd + ")( )?", ""); @@ -123,7 +132,7 @@ public class MessageCommandContext extends CommandContext { @Override public String parseCommandName() { String rawMessage = message.getContentDisplay().trim(); - String prefix = Settings.getInstance().get("NETNEUTRALITY_BOT_PREFIX", "$"); + String prefix = Settings.getInstance().getPrefix(); if (rawMessage.startsWith(prefix)) { rawMessage = rawMessage.replaceFirst(String.format("^[%s\\s]{1,}", prefix), "").trim(); @@ -137,7 +146,7 @@ public class MessageCommandContext extends CommandContext { @Override public String getSubCommand() { - if (getArgs().length > 0) { + if (!getArgs().isEmpty()) { return getArgument(0); } diff --git a/src/main/java/me/bobert/netneutrality/context/tasks/EmojiTaskContext.java b/src/main/java/me/bobert/netneutrality/context/tasks/EmojiTaskContext.java index 29eeb5c..a65f1f6 100644 --- a/src/main/java/me/bobert/netneutrality/context/tasks/EmojiTaskContext.java +++ b/src/main/java/me/bobert/netneutrality/context/tasks/EmojiTaskContext.java @@ -7,8 +7,6 @@ package me.bobert.netneutrality.context.tasks; import me.bobert.netneutrality.context.AsyncContext; import me.bobert.netneutrality.core.context.TaskContext; -import net.dv8tion.jda.api.entities.MessageReaction; -import net.dv8tion.jda.api.entities.emoji.EmojiUnion; import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; import net.dv8tion.jda.api.interactions.InteractionHook; import net.dv8tion.jda.api.interactions.components.LayoutComponent; @@ -19,20 +17,12 @@ import java.util.function.Consumer; public class EmojiTaskContext extends TaskContext { private final MessageReactionAddEvent event; - private final EmojiUnion emoji; public EmojiTaskContext(MessageReactionAddEvent event) { - super(event.getJDA(), event.getGuild(), event.getChannel(), event.getMember(), event.getUser()); + super(event.getJDA(), event.isFromGuild() ? event.getGuild() : null, event.getChannel(), event.getMember(), event.getUser()); this.event = event; - this.emoji = event.getEmoji(); - } - - public String getEmoji() { - return emoji.getAsReactionCode(); - } - - public MessageReaction getReaction() { - return event.getReaction(); + addContextData("emoji", event.getEmoji()); + addContextData("emoji-code", event.getEmoji().getAsReactionCode()); } @Override diff --git a/src/main/java/me/bobert/netneutrality/context/tasks/ModalTaskContext.java b/src/main/java/me/bobert/netneutrality/context/tasks/ModalTaskContext.java index 815bebf..ce89a62 100644 --- a/src/main/java/me/bobert/netneutrality/context/tasks/ModalTaskContext.java +++ b/src/main/java/me/bobert/netneutrality/context/tasks/ModalTaskContext.java @@ -15,6 +15,7 @@ public class ModalTaskContext extends TaskContext implements InteractionContext public ModalTaskContext(ModalInteractionEvent event) { super(event.getJDA(), event.getGuild(), event.getChannel(), event.getMember(), event.getUser()); this.event = event; + addContextData("values", event.getValues()); } @Override diff --git a/src/main/java/me/bobert/netneutrality/core/context/Context.java b/src/main/java/me/bobert/netneutrality/core/context/Context.java index 022d0fd..b13ddf6 100644 --- a/src/main/java/me/bobert/netneutrality/core/context/Context.java +++ b/src/main/java/me/bobert/netneutrality/core/context/Context.java @@ -20,7 +20,6 @@ import net.dv8tion.jda.api.interactions.modals.Modal; import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.api.utils.messages.MessageEditData; -import java.util.Arrays; import java.util.List; import java.util.function.Consumer; @@ -69,11 +68,19 @@ public interface Context { reply(messageCreateData, false, List.of(), asyncMessage -> {}); } + default void reply(MessageCreateData messageCreateData, List components) { + reply(messageCreateData, false, components, asyncMessage -> {}); + } + default void reply(String message) { reply(MessageCreateData.fromContent(message)); } - default void reply(MessageEmbed... embeds) { + default void reply(MessageEmbed embed) { + reply(List.of(embed)); + } + + default void reply(List embeds) { reply(MessageCreateData.fromEmbeds(embeds)); } @@ -103,13 +110,17 @@ public interface Context { } default void edit(MessageEmbed embed) { - edit(MessageEditData.fromEmbeds(embed)); + edit(List.of(embed), List.of()); } - default void edit(MessageEmbed embeds, List components) { + default void edit(List embeds, List components) { edit(MessageEditData.fromEmbeds(embeds), components); } + default void edit(MessageEmbed embed, List components) { + edit(List.of(embed), components); + } + default void edit(String format, Object... arguments) { edit(String.format(format, arguments)); } @@ -154,11 +165,15 @@ public interface Context { } default void sendMessageInPrivate(String message) { - sendMessageInPrivate(MessageCreateData.fromContent(message)); + sendMessageInPrivate(message, List.of()); } - default void sendMessageInPrivate(MessageEmbed... embeds) { - sendMessageInPrivate(Arrays.asList(embeds)); + default void sendMessageInPrivate(String message, List components) { + sendMessageInPrivate(MessageCreateData.fromContent(message), components); + } + + default void sendMessageInPrivate(MessageEmbed embed) { + sendMessageInPrivate(List.of(embed)); } default void sendMessageInPrivate(List embeds) { diff --git a/src/main/java/me/bobert/netneutrality/core/context/TaskContext.java b/src/main/java/me/bobert/netneutrality/core/context/TaskContext.java index 391726f..4fd23a7 100644 --- a/src/main/java/me/bobert/netneutrality/core/context/TaskContext.java +++ b/src/main/java/me/bobert/netneutrality/core/context/TaskContext.java @@ -12,10 +12,15 @@ import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.interactions.modals.Modal; +import java.util.HashMap; +import java.util.Map; + public abstract class TaskContext extends AbstractContext { + private final Map contextData; public TaskContext(JDA jda, Guild guild, MessageChannel channel, Member member, User user) { super(jda, guild, channel, member, user); + this.contextData = new HashMap<>(); } @Override @@ -29,4 +34,12 @@ public abstract class TaskContext extends AbstractContext { } public abstract String getId(); + + public void addContextData(String key, Object value) { + contextData.put(key, value); + } + + public Object getContextData(String key) { + return contextData.get(key); + } } diff --git a/src/main/java/me/bobert/netneutrality/core/tasks/AbstractBuiltInTask.java b/src/main/java/me/bobert/netneutrality/core/tasks/AbstractBuiltInTask.java new file mode 100644 index 0000000..ae3e4eb --- /dev/null +++ b/src/main/java/me/bobert/netneutrality/core/tasks/AbstractBuiltInTask.java @@ -0,0 +1,36 @@ +package me.bobert.netneutrality.core.tasks; +/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +import me.bobert.netneutrality.core.context.CommandContext; + +public abstract class AbstractBuiltInTask extends AbstractTask implements BuiltInTask { + + @Override + public String getName() { + return getId(); + } + + @Override + public boolean isInsertable() { + return true; + } + + @Override + public boolean oneshot() { + return false; + } + + @Override + public boolean isExpired() { + return false; + } + + @Override + public void replyToInteraction(CommandContext context) { + // Task is loaded at runtime, this will never be called + } +} diff --git a/src/main/java/me/bobert/netneutrality/core/tasks/AbstractPersistableTask.java b/src/main/java/me/bobert/netneutrality/core/tasks/AbstractPersistableTask.java index 0edcbee..dc71c77 100644 --- a/src/main/java/me/bobert/netneutrality/core/tasks/AbstractPersistableTask.java +++ b/src/main/java/me/bobert/netneutrality/core/tasks/AbstractPersistableTask.java @@ -27,7 +27,7 @@ public abstract class AbstractPersistableTask extends AbstractTask implements Pe @Override public void replyToInteraction(CommandContext context) { - + // Task loaded from database, this will never be called } @Override diff --git a/src/main/java/me/bobert/netneutrality/core/tasks/AbstractTask.java b/src/main/java/me/bobert/netneutrality/core/tasks/AbstractTask.java index 6da8833..56e1bfd 100644 --- a/src/main/java/me/bobert/netneutrality/core/tasks/AbstractTask.java +++ b/src/main/java/me/bobert/netneutrality/core/tasks/AbstractTask.java @@ -25,6 +25,11 @@ public abstract class AbstractTask implements Task { return creationTime; } + @Override + public TaskButtonCreator createButton() { + return new TaskButtonCreator(getId()); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/me/bobert/netneutrality/core/tasks/BuiltInTask.java b/src/main/java/me/bobert/netneutrality/core/tasks/BuiltInTask.java new file mode 100644 index 0000000..686a5e4 --- /dev/null +++ b/src/main/java/me/bobert/netneutrality/core/tasks/BuiltInTask.java @@ -0,0 +1,23 @@ +package me.bobert.netneutrality.core.tasks; +/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +import java.lang.reflect.InvocationTargetException; + +/** + * Represents a task that has a known ID and is loaded at runtime. + * This can be any task and is not necessarily a button. + */ +public interface BuiltInTask extends Task { + static TaskButtonCreator createButton(Class clazz) { + try { + BuiltInTask task = clazz.getConstructor().newInstance(); + return new TaskButtonCreator(task.getId()); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/me/bobert/netneutrality/core/tasks/Task.java b/src/main/java/me/bobert/netneutrality/core/tasks/Task.java index 4f6e8b8..15f6b08 100644 --- a/src/main/java/me/bobert/netneutrality/core/tasks/Task.java +++ b/src/main/java/me/bobert/netneutrality/core/tasks/Task.java @@ -8,11 +8,11 @@ package me.bobert.netneutrality.core.tasks; import me.bobert.netneutrality.core.context.CommandContext; import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.core.tasks.trait.WithChildren; +import net.dv8tion.jda.api.interactions.components.buttons.Button; import java.time.OffsetDateTime; public interface Task { - /** *

This method should generate a unique ID to differentiate it from other tasks.

*

@@ -59,4 +59,30 @@ public interface Task { boolean isExpired(); OffsetDateTime getCreationTime(); + + TaskButtonCreator createButton(); + + class TaskButtonCreator { + private final String id; + + public TaskButtonCreator(String id) { + this.id = id; + } + + public Button primary(String label) { + return Button.primary(id, label); + } + + public Button secondary(String label) { + return Button.secondary(id, label); + } + + public Button success(String label) { + return Button.success(id, label); + } + + public Button danger(String label) { + return Button.danger(id, label); + } + } } diff --git a/src/main/java/me/bobert/netneutrality/core/tasks/TaskManager.java b/src/main/java/me/bobert/netneutrality/core/tasks/TaskManager.java index 1b45860..26b1f1e 100644 --- a/src/main/java/me/bobert/netneutrality/core/tasks/TaskManager.java +++ b/src/main/java/me/bobert/netneutrality/core/tasks/TaskManager.java @@ -21,28 +21,22 @@ import me.bobert.netneutrality.thread.CleanupTaskThread; import net.dv8tion.jda.api.interactions.InteractionHook; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.reflections.Reflections; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.*; import java.util.concurrent.TimeUnit; public class TaskManager { private static final Logger logger = LogManager.getLogger(TaskManager.class); - private static final ScheduledExecutorService executor = ThreadManager.getScheduledExecutor(); private static TaskManager instance; private final TaskService taskService; private final Map tasks; - private final Map persistableTasks; private final Map deletableTasksContext; - private ScheduledFuture cleanupThread; private TaskManager() { this.tasks = new HashMap<>(); - this.persistableTasks = new HashMap<>(); this.deletableTasksContext = new HashMap<>(); this.taskService = new TaskService(this); } @@ -56,7 +50,10 @@ public class TaskManager { } public void init() { + loadBuiltInTasks(); taskService.loadTasks(); + + ThreadManager.getScheduledExecutor().scheduleWithFixedDelay(new CleanupTaskThread(), 1, 5, TimeUnit.MINUTES); } public TaskService getTaskService() { @@ -64,37 +61,25 @@ public class TaskManager { } public Task getTask(String id) { - Task task = tasks.get(id); - - if (task == null) { - task = persistableTasks.get(id); - } - - return task; + return tasks.get(id); } public Collection getTasks() { return tasks.values(); } - public Map getPersistableTaskMap() { - return persistableTasks; + public Map getTaskMap() { + return tasks; } public boolean exists(String id) { - boolean exists = tasks.containsKey(id); - - if (!exists) { - exists = persistableTasks.containsKey(id); - } - - return exists; + return tasks.containsKey(id); } public void insert(CommandContext context, Task task) { String id = task.getId(); - if (tasks.containsKey(id) || persistableTasks.containsKey(id)) { + if (tasks.containsKey(id)) { context.reply("A task with the same id already exists!"); return; } @@ -108,12 +93,11 @@ public class TaskManager { if (task.isInsertable()) { logger.info("Inserting task: {}", task); - if (task instanceof PersistableTask) { - taskService.persistTask((PersistableTask) task); - persistableTasks.put(id, (PersistableTask) task); - } else { - tasks.put(id, task); + if (task instanceof PersistableTask persistableTask) { + taskService.persistTask(persistableTask); } + + tasks.put(id, task); } if (task instanceof WithChildren taskWithChildren) { @@ -123,10 +107,6 @@ public class TaskManager { insert(context, child); } } - - if (!tasks.isEmpty() && cleanupThread == null) { - cleanupThread = executor.scheduleWithFixedDelay(new CleanupTaskThread(), 1, 5, TimeUnit.MINUTES); - } } public void removeTask(Task task) { @@ -136,19 +116,11 @@ public class TaskManager { logger.debug("Removing task: {}", task); tasks.remove(id); } - - if (tasks.isEmpty() && cleanupThread != null) { - cleanupThread.cancel(false); - cleanupThread = null; - } } public void handle(TaskContext context) { - Task task = tasks.get(context.getId()); - - if (task == null) { - task = persistableTasks.get(context.getId()); - } + String taskId = context.getId(); + Task task = tasks.get(taskId); if (task == null && (context instanceof ModalTaskContext || context instanceof ButtonTaskContext)) { context.replyEphemeral("This task is no longer available, someone might have already used it or it might have expired"); @@ -182,6 +154,27 @@ public class TaskManager { } } + private void loadBuiltInTasks() { + logger.info("Loading built-in tasks..."); + + Set> classes = new Reflections("me.bobert.netneutrality.tasks").getSubTypesOf(BuiltInTask.class); + for (Class s : classes) { + try { + if (Modifier.isAbstract(s.getModifiers())) { + continue; + } + + BuiltInTask task = s.getConstructor().newInstance(); + + logger.info("Loaded task: {}", task); + tasks.put(task.getId(), task); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException e) { + logger.error("Failed to instantiate built-in task", e); + } + } + } + private void deleteInteraction(Task task) { if (task instanceof WithParent taskWithParent) { Task parent = (Task) taskWithParent.getParentTask(); @@ -220,6 +213,10 @@ public class TaskManager { } private void removeTaskAndChildTasks(Task task) { + if (task instanceof BuiltInTask) { + return; + } + tasks.remove(task.getId()); if (task instanceof WithParent taskWithParent && !taskWithParent.shouldKeepChilds()) { @@ -233,6 +230,10 @@ public class TaskManager { } private void reinsertTaskAndChildTasks(Task task) { + if (task instanceof BuiltInTask) { + return; + } + tasks.put(task.getId(), task); if (task instanceof WithParent taskWithParent && taskWithParent.shouldKeepChilds()) { diff --git a/src/main/java/me/bobert/netneutrality/core/tasks/trait/WithChildren.java b/src/main/java/me/bobert/netneutrality/core/tasks/trait/WithChildren.java index 2a09fe4..32a149b 100644 --- a/src/main/java/me/bobert/netneutrality/core/tasks/trait/WithChildren.java +++ b/src/main/java/me/bobert/netneutrality/core/tasks/trait/WithChildren.java @@ -11,7 +11,6 @@ import me.bobert.netneutrality.core.tasks.TaskManager; import java.util.List; public interface WithChildren { - List getChildTasks(); default void removeAllChildTasks() { diff --git a/src/main/java/me/bobert/netneutrality/db/GSettings.java b/src/main/java/me/bobert/netneutrality/db/GSettings.java index 1c4b276..64f094a 100644 --- a/src/main/java/me/bobert/netneutrality/db/GSettings.java +++ b/src/main/java/me/bobert/netneutrality/db/GSettings.java @@ -10,7 +10,6 @@ public enum GSettings { MUSIC_ROLE("MUSIC_ROLE", ""), MUSIC_CHANNEL("MUSIC_CHANNEL", ""), MUSIC_VOLUME("MUSIC_VOLUME", "30"), - MUSIC_SEARCHRESULTS_LIMIT("MUSIC_SEARCHRESULTS_LIMIT", "5"), MUSIC_MAXPLAYLISTSIZE("MUSIC_MAXPLAYLISTSIZE", "20"); private final String name; diff --git a/src/main/java/me/bobert/netneutrality/db/service/TaskService.java b/src/main/java/me/bobert/netneutrality/db/service/TaskService.java index 4c55388..68a6815 100644 --- a/src/main/java/me/bobert/netneutrality/db/service/TaskService.java +++ b/src/main/java/me/bobert/netneutrality/db/service/TaskService.java @@ -43,8 +43,13 @@ public class TaskService { JSONObject json = new JSONObject(payload); PersistableTask task = creator.fromPayload(json); + if (TaskManager.getInstance().exists(task.getId())) { + logger.error("Task with id {} already exists", task.getId()); + continue; + } + logger.info("Loaded task: {}", task); - TaskManager.getInstance().getPersistableTaskMap().put(task.getId(), task); + TaskManager.getInstance().getTaskMap().put(task.getId(), task); } catch (Exception e) { logger.error("Error loading task: {}", payload, e); } @@ -76,6 +81,6 @@ public class TaskService { TaskRepository taskRepository = new TaskRepository(); taskRepository.deleteBy(task.getId()); - taskManager.getPersistableTaskMap().remove(task.getId()); + taskManager.getTaskMap().remove(task.getId()); } } diff --git a/src/main/java/me/bobert/netneutrality/music/TrackLoadingHandler.java b/src/main/java/me/bobert/netneutrality/music/TrackLoadingHandler.java index 752774e..3bb61b0 100644 --- a/src/main/java/me/bobert/netneutrality/music/TrackLoadingHandler.java +++ b/src/main/java/me/bobert/netneutrality/music/TrackLoadingHandler.java @@ -57,7 +57,7 @@ public class TrackLoadingHandler implements AudioLoadResultHandler { public void playlistLoaded(AudioPlaylist playlist) { logger.debug("Guild {}: playlist loaded: {}", guild.getId(), identifier); - TaskManager.getInstance().insert(context, new LoadPlaylistTask(playlist)); + TaskManager.getInstance().insert(context, new LoadPlaylistTask(playlist, type)); } @Override diff --git a/src/main/java/me/bobert/netneutrality/music/TrackScheduler.java b/src/main/java/me/bobert/netneutrality/music/TrackScheduler.java index 4fb3a89..47d2b5f 100644 --- a/src/main/java/me/bobert/netneutrality/music/TrackScheduler.java +++ b/src/main/java/me/bobert/netneutrality/music/TrackScheduler.java @@ -13,7 +13,7 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; import me.bobert.netneutrality.context.MusicChannelContext; import me.bobert.netneutrality.core.LogHandler; import me.bobert.netneutrality.core.context.Context; -import me.bobert.netneutrality.utils.MessageFunction; +import me.bobert.netneutrality.exceptions.ContextException; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import org.apache.logging.log4j.LogManager; @@ -115,13 +115,8 @@ public class TrackScheduler extends AudioEventAdapter { @Override public void onTrackException(AudioPlayer player, AudioTrack track, FriendlyException exception) { logger.error("Guild {}: exception while playing track: {}", guild.getId(), track.getIdentifier()); - LogHandler.log(exception); - context.reply( - MessageFunction.buildSentryErrorMessage( - new RuntimeException(String.format("Error while playing track: %s", track.getInfo().title), exception) - ) - ); + LogHandler.log(new ContextException(String.format("Error while playing track: %s", track.getInfo().title), getContext(), exception)); } @Override @@ -132,7 +127,7 @@ public class TrackScheduler extends AudioEventAdapter { lastStuckTrack = track; logger.debug("Trying to load stuck track again: {}", track.getIdentifier()); - context.async("Current track is stuck, trying to load it again", asyncMessage -> { + context.async("Current track is stuck, trying to load it again", asyncContext -> { try { TrackInfo info = queueManager.peekHeadOfQueue(); if (info != null && info.getTrack().getIdentifier().equals(track.getIdentifier())) { @@ -152,15 +147,15 @@ public class TrackScheduler extends AudioEventAdapter { playing.setPosition(lastPosition); lastStuckTrack = null; } else { - asyncMessage.edit("Failed to seek track to last timestamp, the track will play from the beginning"); + asyncContext.edit("Failed to seek track to last timestamp, the track will play from the beginning"); } } else { - asyncMessage.edit("Failed to load last playing track, skipping to next.."); + asyncContext.edit("Failed to load last playing track, skipping to next.."); queueManager.startNextTrack(); } } catch (Exception e) { LogHandler.log(e); - asyncMessage.edit("Failed to load last playing track, skipping to next.."); + asyncContext.edit("Failed to load last playing track, skipping to next.."); queueManager.startNextTrack(); } }); diff --git a/src/main/java/me/bobert/netneutrality/tasks/ButtonTask.java b/src/main/java/me/bobert/netneutrality/tasks/ButtonTask.java index 64132eb..03bf819 100644 --- a/src/main/java/me/bobert/netneutrality/tasks/ButtonTask.java +++ b/src/main/java/me/bobert/netneutrality/tasks/ButtonTask.java @@ -5,8 +5,6 @@ package me.bobert.netneutrality.tasks; * https://discord.gg/qUa6zNFZsd */ -import me.bobert.netneutrality.context.tasks.ButtonTaskContext; -import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.core.tasks.AbstractTask; import java.time.OffsetDateTime; @@ -20,17 +18,6 @@ public abstract class ButtonTask extends AbstractTask { return id.toString(); } - @Override - public void execute(TaskContext context) { - if (context instanceof ButtonTaskContext) { - execute((ButtonTaskContext) context); - } else { - throw new IllegalArgumentException("Invalid context for this task"); - } - } - - public abstract void execute(ButtonTaskContext context); - @Override public boolean oneshot() { return true; diff --git a/src/main/java/me/bobert/netneutrality/tasks/EmojiTask.java b/src/main/java/me/bobert/netneutrality/tasks/EmojiTask.java index a953d24..75a1487 100644 --- a/src/main/java/me/bobert/netneutrality/tasks/EmojiTask.java +++ b/src/main/java/me/bobert/netneutrality/tasks/EmojiTask.java @@ -5,8 +5,6 @@ package me.bobert.netneutrality.tasks; * https://discord.gg/qUa6zNFZsd */ -import me.bobert.netneutrality.context.tasks.EmojiTaskContext; -import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.core.tasks.AbstractPersistableTask; public abstract class EmojiTask extends AbstractPersistableTask { @@ -30,15 +28,4 @@ public abstract class EmojiTask extends AbstractPersistableTask { public String getId() { return String.format("%s:%s", getGuildId(), getMessageId()); } - - @Override - public void execute(TaskContext context) { - if (context instanceof EmojiTaskContext) { - execute((EmojiTaskContext) context); - } else { - throw new IllegalArgumentException("Invalid context for this task"); - } - } - - public abstract void execute(EmojiTaskContext context); } diff --git a/src/main/java/me/bobert/netneutrality/tasks/ModalTask.java b/src/main/java/me/bobert/netneutrality/tasks/ModalTask.java index 6b6813b..b55fc10 100644 --- a/src/main/java/me/bobert/netneutrality/tasks/ModalTask.java +++ b/src/main/java/me/bobert/netneutrality/tasks/ModalTask.java @@ -5,11 +5,12 @@ package me.bobert.netneutrality.tasks; * https://discord.gg/qUa6zNFZsd */ -import me.bobert.netneutrality.context.tasks.ModalTaskContext; import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.core.tasks.AbstractTask; +import net.dv8tion.jda.api.interactions.modals.ModalMapping; import java.time.OffsetDateTime; +import java.util.List; import java.util.UUID; public abstract class ModalTask extends AbstractTask { @@ -20,17 +21,6 @@ public abstract class ModalTask extends AbstractTask { return id.toString(); } - @Override - public void execute(TaskContext context) { - if (context instanceof ModalTaskContext) { - execute((ModalTaskContext) context); - } else { - throw new IllegalArgumentException("Invalid context for this task"); - } - } - - public abstract void execute(ModalTaskContext context); - @Override public boolean oneshot() { return true; @@ -40,4 +30,13 @@ public abstract class ModalTask extends AbstractTask { public boolean isExpired() { return getCreationTime().plusMinutes(5).isBefore(OffsetDateTime.now()); } + + public ModalMapping getValue(String key, TaskContext context) { + List mappings = (List) context.getContextData("values"); + return mappings.stream() + .filter(o -> o instanceof ModalMapping) + .map(o -> (ModalMapping) o) + .filter(mapping -> mapping.getId().equals(key)) + .findFirst().orElse(null); + } } diff --git a/src/main/java/me/bobert/netneutrality/tasks/emoji/EmojiReactionRoleTask.java b/src/main/java/me/bobert/netneutrality/tasks/emoji/EmojiReactionRoleTask.java index 0fa2f6f..2755c4b 100644 --- a/src/main/java/me/bobert/netneutrality/tasks/emoji/EmojiReactionRoleTask.java +++ b/src/main/java/me/bobert/netneutrality/tasks/emoji/EmojiReactionRoleTask.java @@ -5,7 +5,7 @@ package me.bobert.netneutrality.tasks.emoji; * https://discord.gg/qUa6zNFZsd */ -import me.bobert.netneutrality.context.tasks.EmojiTaskContext; +import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.tasks.EmojiTask; import net.dv8tion.jda.api.entities.Role; @@ -43,9 +43,11 @@ public class EmojiReactionRoleTask extends EmojiTask { } @Override - public void execute(EmojiTaskContext context) { - if (getEmojiMapping().containsKey(context.getEmoji())) { - Role role = context.getGuild().getRoleById(getEmojiMapping().get(context.getEmoji())); + public void execute(TaskContext context) { + String emoji = (String) context.getContextData("emoji-code"); + + if (getEmojiMapping().containsKey(emoji)) { + Role role = context.getGuild().getRoleById(getEmojiMapping().get(emoji)); if (role != null) { context.getGuildManager().addRolesToMember(context.getGuildUser(), role); diff --git a/src/main/java/me/bobert/netneutrality/tasks/git/ReportIssueTask.java b/src/main/java/me/bobert/netneutrality/tasks/git/ReportIssueTask.java index fd147bf..dc27417 100644 --- a/src/main/java/me/bobert/netneutrality/tasks/git/ReportIssueTask.java +++ b/src/main/java/me/bobert/netneutrality/tasks/git/ReportIssueTask.java @@ -6,9 +6,9 @@ package me.bobert.netneutrality.tasks.git; */ import io.sentry.Sentry; -import me.bobert.netneutrality.context.tasks.ModalTaskContext; import me.bobert.netneutrality.core.LogHandler; import me.bobert.netneutrality.core.context.CommandContext; +import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.tasks.ModalTask; import me.bobert.netneutrality.utils.Settings; import net.dv8tion.jda.api.entities.User; @@ -53,7 +53,7 @@ public class ReportIssueTask extends ModalTask { } @Override - public void execute(ModalTaskContext context) { + public void execute(TaskContext context) { context.ephemeral(); String gitlabHost = Settings.getInstance().get("GITLAB_HOST"); @@ -66,8 +66,8 @@ public class ReportIssueTask extends ModalTask { return; } - ModalMapping modalTitle = context.getEvent().getValue("title"); - ModalMapping modalDescription = context.getEvent().getValue("description"); + ModalMapping modalTitle = getValue("title", context); + ModalMapping modalDescription = getValue("description", context); if (modalTitle == null || modalDescription == null) { context.reply("Failed to create issue."); diff --git a/src/main/java/me/bobert/netneutrality/tasks/help/BotInfo.java b/src/main/java/me/bobert/netneutrality/tasks/help/BotInfo.java new file mode 100644 index 0000000..5b78d72 --- /dev/null +++ b/src/main/java/me/bobert/netneutrality/tasks/help/BotInfo.java @@ -0,0 +1,23 @@ +package me.bobert.netneutrality.tasks.help; +/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +import me.bobert.netneutrality.core.context.TaskContext; +import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask; + +public class BotInfo extends AbstractBuiltInTask { + + @Override + public String getId() { + return "help-info"; + } + + @Override + public void execute(TaskContext context) { + context.reply("For information about the bot and to follow the development, " + + "you can join the discord here: https://discord.gg/udVJwTgV"); + } +} diff --git a/src/main/java/me/bobert/netneutrality/tasks/help/CommandHelp.java b/src/main/java/me/bobert/netneutrality/tasks/help/CommandHelp.java new file mode 100644 index 0000000..f6bd2d5 --- /dev/null +++ b/src/main/java/me/bobert/netneutrality/tasks/help/CommandHelp.java @@ -0,0 +1,23 @@ +package me.bobert.netneutrality.tasks.help; +/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +import me.bobert.netneutrality.core.context.TaskContext; +import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask; +import me.bobert.netneutrality.utils.MessageFunction; + +public class CommandHelp extends AbstractBuiltInTask { + + @Override + public String getId() { + return "help-commands"; + } + + @Override + public void execute(TaskContext context) { + context.reply(MessageFunction.buildHelpMessage()); + } +} diff --git a/src/main/java/me/bobert/netneutrality/tasks/help/ReportBug.java b/src/main/java/me/bobert/netneutrality/tasks/help/ReportBug.java new file mode 100644 index 0000000..d903675 --- /dev/null +++ b/src/main/java/me/bobert/netneutrality/tasks/help/ReportBug.java @@ -0,0 +1,23 @@ +package me.bobert.netneutrality.tasks.help; +/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +import me.bobert.netneutrality.core.context.TaskContext; +import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask; + +public class ReportBug extends AbstractBuiltInTask { + + @Override + public String getId() { + return "help-reportbug"; + } + + @Override + public void execute(TaskContext context) { + context.reply("To report a buuug with the bot, you can either use the /report-bug command " + + "or join the discord here: https://discord.gg/udVJwTgV"); + } +} diff --git a/src/main/java/me/bobert/netneutrality/tasks/music/AddAllTracksTask.java b/src/main/java/me/bobert/netneutrality/tasks/music/AddAllTracksTask.java index b225e3f..91114da 100644 --- a/src/main/java/me/bobert/netneutrality/tasks/music/AddAllTracksTask.java +++ b/src/main/java/me/bobert/netneutrality/tasks/music/AddAllTracksTask.java @@ -6,12 +6,11 @@ package me.bobert.netneutrality.tasks.music; */ import com.sedmelluq.discord.lavaplayer.track.AudioTrack; -import me.bobert.netneutrality.context.tasks.ButtonTaskContext; import me.bobert.netneutrality.core.context.CommandContext; +import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.core.tasks.trait.WithParent; import me.bobert.netneutrality.music.MusicManager; import me.bobert.netneutrality.music.SourceFinder; -import me.bobert.netneutrality.music.TrackScheduler; import me.bobert.netneutrality.tasks.ButtonTask; import me.bobert.netneutrality.utils.MessageFunction; import me.bobert.netneutrality.utils.MusicUtils; @@ -39,7 +38,7 @@ public class AddAllTracksTask extends ButtonTask implements WithParent childrens = new ArrayList<>(); private final AudioPlaylist playlist; + private final SourceFinder.AudioSourceType sourceType; - public LoadPlaylistTask(AudioPlaylist playlist) { + public LoadPlaylistTask(AudioPlaylist playlist, SourceFinder.AudioSourceType sourceType) { this.playlist = playlist; + this.sourceType = sourceType; } public AudioPlaylist getPlaylist() { @@ -56,9 +56,7 @@ public class LoadPlaylistTask extends ButtonTask implements WithChildren, Deleta return; } - int searchResultsLimit = Integer.parseInt(context.getGuildManager() - .getGuildConfigManager() - .getSetting(GSettings.MUSIC_SEARCHRESULTS_LIMIT)); + int searchResultsLimit = 5; // Max number of buttons per row int maxPlaylistSizeBeforeAsking = Integer.parseInt(context.getGuildManager() .getGuildConfigManager() .getSetting(GSettings.MUSIC_MAXPLAYLISTSIZE)); @@ -72,8 +70,7 @@ public class LoadPlaylistTask extends ButtonTask implements WithChildren, Deleta AudioTrack track = searchResults.get(i); Task buttonTask = new LoadTrackFromPlaylistTask(this, track); - Button button = Button.primary(buttonTask.getId(), String.valueOf(i + 1)); - buttonList.add(button); + buttonList.add(buttonTask.createButton().primary(String.valueOf(i + 1))); childrens.add(buttonTask); } @@ -98,25 +95,26 @@ public class LoadPlaylistTask extends ButtonTask implements WithChildren, Deleta if (MusicUtils.connect(context)) { manager.getQueueManager().queue(tracks, context.getGuildUser()); - context.edit(MessageFunction.buildAddingPlaylistMessage(tracks, playlist.getName(), context.getGuildUser(), Youtube)); + context.edit(MessageFunction.buildAddingPlaylistMessage(tracks, playlist.getName(), context.getGuildUser(), sourceType)); } } @Override - public void execute(ButtonTaskContext context) { + public void execute(TaskContext context) { // Only the buttons will get executed, this task is only used to insert them } private ActionRow commonButtons(List tracks, String addAllText, String cancelText) { Task addAllTracksTask = new AddAllTracksTask(this, tracks); - Button addAllButton = Button.success(addAllTracksTask.getId(), addAllText).withEmoji(Emoji.fromFormatted("U+1F60E")); childrens.add(addAllTracksTask); Task cancelTask = new CancelLoadTask(this); - Button cancelButton = Button.danger(cancelTask.getId(), cancelText).withEmoji(Emoji.fromFormatted("U+1F92E")); childrens.add(cancelTask); - return ActionRow.of(addAllButton, cancelButton); + return ActionRow.of( + addAllTracksTask.createButton().success(addAllText).withEmoji(Emoji.fromFormatted("U+1F60E")), + cancelTask.createButton().danger(cancelText).withEmoji(Emoji.fromFormatted("U+1F92E")) + ); } @Override diff --git a/src/main/java/me/bobert/netneutrality/tasks/music/LoadTrackFromPlaylistTask.java b/src/main/java/me/bobert/netneutrality/tasks/music/LoadTrackFromPlaylistTask.java index 5580f6a..d073440 100644 --- a/src/main/java/me/bobert/netneutrality/tasks/music/LoadTrackFromPlaylistTask.java +++ b/src/main/java/me/bobert/netneutrality/tasks/music/LoadTrackFromPlaylistTask.java @@ -6,8 +6,8 @@ package me.bobert.netneutrality.tasks.music; */ import com.sedmelluq.discord.lavaplayer.track.AudioTrack; -import me.bobert.netneutrality.context.tasks.ButtonTaskContext; import me.bobert.netneutrality.core.context.CommandContext; +import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.core.tasks.trait.WithParent; import me.bobert.netneutrality.music.MusicManager; import me.bobert.netneutrality.music.SourceFinder; @@ -36,7 +36,7 @@ public class LoadTrackFromPlaylistTask extends ButtonTask implements WithParent< } @Override - public void execute(ButtonTaskContext context) { + public void execute(TaskContext context) { MusicManager manager = MusicManager.get(context.getGuild()); Member member = context.getGuildUser(); diff --git a/src/main/java/me/bobert/netneutrality/thread/CleanupTaskThread.java b/src/main/java/me/bobert/netneutrality/thread/CleanupTaskThread.java index 94ec25c..697597a 100644 --- a/src/main/java/me/bobert/netneutrality/thread/CleanupTaskThread.java +++ b/src/main/java/me/bobert/netneutrality/thread/CleanupTaskThread.java @@ -4,21 +4,35 @@ package me.bobert.netneutrality.thread;/* * https://discord.gg/qUa6zNFZsd */ +import me.bobert.netneutrality.core.tasks.BuiltInTask; +import me.bobert.netneutrality.core.tasks.PersistableTask; import me.bobert.netneutrality.core.tasks.Task; import me.bobert.netneutrality.core.tasks.TaskManager; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.List; + public class CleanupTaskThread implements Runnable { private static final Logger logger = LogManager.getLogger(CleanupTaskThread.class); @Override public void run() { - logger.info("Cleaning up tasks.."); - - TaskManager.getInstance().getTasks() + List tasks = TaskManager.getInstance().getTasks() .stream() + .filter(task -> !(task instanceof PersistableTask)) + .filter(task -> !(task instanceof BuiltInTask)) .filter(Task::isExpired) - .forEach(task -> TaskManager.getInstance().removeTask(task)); + .toList(); + + if (!tasks.isEmpty()) { + logger.info("Cleaning up tasks.."); + + for (Task task : tasks) { + TaskManager.getInstance().removeTask(task); + } + } + + } } diff --git a/src/main/java/me/bobert/netneutrality/utils/MessageFunction.java b/src/main/java/me/bobert/netneutrality/utils/MessageFunction.java index 798c456..2c5efe6 100644 --- a/src/main/java/me/bobert/netneutrality/utils/MessageFunction.java +++ b/src/main/java/me/bobert/netneutrality/utils/MessageFunction.java @@ -200,39 +200,54 @@ public class MessageFunction { return embed.build(); } - public static List buildHelpMessage() { - Map help = new HashMap<>(); + public static String buildHelpMessage() { + Map help = new HashMap<>(); for (Command command : CommandManager.commands.values()) { - if (command.getType() == null) + if (command.getType() == null) { continue; - - String description = "No description yet"; + } if (command.isEnabled() && command.getType() != CommandType.UNLISTED) { - if (command.getDescription() != null) - description = command.getDescription(); + String description = "No description yet"; - EmbedBuilder message; + if (command.getDescription() != null) { + description = command.getDescription(); + } + + String message; if (help.containsKey(command.getType())) { message = help.get(command.getType()); } else { - help.put(command.getType(), message = new EmbedBuilder()); + help.put(command.getType(), message = ""); } if (message.isEmpty()) { - message.setTitle(command.getType().getDescription() + " commands for NetNeutrality"); - message.setColor(Color.BLUE); + message = "## " + command.getType() + " commands"; } - message.addField(String.format("%s", command.getCommandName()), description, false); + message += "\n- /" + command.getCommandName() + " -> " + description; + help.put(command.getType(), message); } } - List messages = new ArrayList<>(); - help.values().forEach(embedBuilder -> messages.add(embedBuilder.build())); + String subtext = "\n\n" + + "-# The bot supports both types of commands: slash (/) and message ($), " + + "however not all slash commands might have a corresponding message command." + + "-# To get help for a specific command, please use /help "; - return messages; + return String.join("\n", help.values()) + subtext; + } + + public static String buildCommandHelpMessage(Command command) { + String message = "## Command info for /" + command.getCommandName(); + if (command.getDescription() != null) { + message += "\n- Description: " + command.getDescription(); + } + + message += "\n\n-# *: required argument"; + + return message; } public static MessageEmbed buildSentryErrorMessage(Exception ex) { diff --git a/src/main/java/me/bobert/netneutrality/utils/Settings.java b/src/main/java/me/bobert/netneutrality/utils/Settings.java index 62d0348..6e9cde9 100644 --- a/src/main/java/me/bobert/netneutrality/utils/Settings.java +++ b/src/main/java/me/bobert/netneutrality/utils/Settings.java @@ -72,6 +72,10 @@ public class Settings { return property; } + public String getPrefix() { + return get("NETNEUTRALITY_BOT_PREFIX", "$"); + } + public String getMavenVersion() { String version = null;