From d9fb6533d3d92f79276328b4266da99dbf6bb967 Mon Sep 17 00:00:00 2001 From: Alex Thomson Date: Sun, 15 Sep 2019 16:53:51 +1200 Subject: [PATCH] Major changes and code cleanup --- build.gradle | 6 +- .../lxgaming/discordmusic/DiscordMusic.java | 59 ++-- .../io/github/lxgaming/discordmusic/Main.java | 2 +- .../discordmusic/command/ClearCommand.java | 22 +- .../discordmusic/command/DebugCommand.java | 41 +-- .../discordmusic/command/HelpCommand.java | 47 ++- .../discordmusic/command/InfoCommand.java | 6 +- .../discordmusic/command/JoinCommand.java | 1 - .../discordmusic/command/PlayCommand.java | 9 +- .../discordmusic/command/PlayingCommand.java | 1 - .../discordmusic/command/QueueCommand.java | 1 - .../discordmusic/command/SearchCommand.java | 24 +- .../discordmusic/command/SelectCommand.java | 14 +- .../discordmusic/command/ShutdownCommand.java | 2 +- .../discordmusic/command/SkipCommand.java | 15 +- .../discordmusic/command/SourcesCommand.java | 28 +- .../discordmusic/command/StopCommand.java | 14 +- .../discordmusic/command/VolumeCommand.java | 5 +- .../discordmusic/configuration/Config.java | 134 ++------ .../configuration/Configuration.java | 18 +- .../category/AccountCategory.java | 53 +--- .../category/GeneralCategory.java | 83 +++++ .../configuration/category/GroupCategory.java | 16 +- .../category/MessageCategory.java | 46 +++ .../category/ServerCategory.java | 23 +- .../category/ServiceCategory.java | 52 +++ .../discordmusic/data/AudioTrackData.java | 83 +++++ .../handler/AudioPlayerLoadResultHandler.java | 26 +- .../handler/AudioPlayerSendHandler.java | 45 +-- .../discordmusic/listener/AudioListener.java | 10 +- .../listener/DiscordListener.java | 33 +- .../discordmusic/manager/AccountManager.java | 63 ++-- .../discordmusic/manager/AudioManager.java | 298 +++++++++++------- .../discordmusic/manager/CommandManager.java | 102 +++--- .../discordmusic/manager/GroupManager.java | 25 +- .../discordmusic/manager/MessageManager.java | 60 ++-- .../discordmusic/manager/ServiceManager.java | 67 +++- .../discordmusic/service/AbstractService.java | 20 +- .../discordmusic/service/MessageService.java | 39 +-- .../discordmusic/util/DiscordData.java | 59 ---- .../lxgaming/discordmusic/util/Reference.java | 6 +- .../discordmusic/util/ShutdownHook.java | 25 +- .../lxgaming/discordmusic/util/Toolbox.java | 82 +++-- 43 files changed, 980 insertions(+), 785 deletions(-) create mode 100644 src/main/java/io/github/lxgaming/discordmusic/configuration/category/GeneralCategory.java create mode 100644 src/main/java/io/github/lxgaming/discordmusic/configuration/category/MessageCategory.java create mode 100644 src/main/java/io/github/lxgaming/discordmusic/configuration/category/ServiceCategory.java create mode 100644 src/main/java/io/github/lxgaming/discordmusic/data/AudioTrackData.java delete mode 100644 src/main/java/io/github/lxgaming/discordmusic/util/DiscordData.java diff --git a/build.gradle b/build.gradle index 35c9a7b..7b8c579 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,7 @@ -apply plugin: "java" -apply plugin: "signing" +plugins { + id "java" + id "signing" +} sourceCompatibility = 1.8 targetCompatibility = 1.8 diff --git a/src/main/java/io/github/lxgaming/discordmusic/DiscordMusic.java b/src/main/java/io/github/lxgaming/discordmusic/DiscordMusic.java index 9a28556..c1e0aff 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/DiscordMusic.java +++ b/src/main/java/io/github/lxgaming/discordmusic/DiscordMusic.java @@ -18,10 +18,13 @@ import io.github.lxgaming.discordmusic.configuration.Config; import io.github.lxgaming.discordmusic.configuration.Configuration; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; import io.github.lxgaming.discordmusic.manager.AccountManager; +import io.github.lxgaming.discordmusic.manager.AudioManager; import io.github.lxgaming.discordmusic.manager.CommandManager; import io.github.lxgaming.discordmusic.manager.MessageManager; import io.github.lxgaming.discordmusic.manager.ServiceManager; +import io.github.lxgaming.discordmusic.service.MessageService; import io.github.lxgaming.discordmusic.util.Reference; import io.github.lxgaming.discordmusic.util.ShutdownHook; import io.github.lxgaming.discordmusic.util.Toolbox; @@ -30,7 +33,6 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.config.Configurator; -import java.nio.file.Path; import java.time.Instant; import java.util.Optional; @@ -39,42 +41,51 @@ public class DiscordMusic { private static DiscordMusic instance; private final Instant startTime; private final Logger logger; - private final Path path; private final Configuration configuration; public DiscordMusic() { instance = this; - startTime = Instant.now(); - logger = LogManager.getLogger(Reference.APP_ID); - path = Toolbox.getPath().orElse(null); - configuration = new Configuration(); + this.startTime = Instant.now(); + this.logger = LogManager.getLogger(Reference.NAME); + this.configuration = new Configuration(Toolbox.getPath()); } - public void loadDiscordMusic() { - getLogger().info("Initializing..."); + public void load() { Runtime.getRuntime().addShutdownHook(new ShutdownHook()); + getLogger().info("Initializing..."); + if (!reload()) { + getLogger().error("Failed to load"); + return; + } - getLogger().info("Loading configuration..."); - getConfiguration().loadConfiguration(); + AccountManager.prepare(); + AudioManager.prepare(); + CommandManager.prepare(); + MessageManager.prepare(); + ServiceManager.prepare(); - reloadLogger(); - AccountManager.buildAccount(); - AccountManager.reloadAccount(); - CommandManager.buildCommands(); - MessageManager.buildColors(); - ServiceManager.buildServices(); getConfiguration().saveConfiguration(); - getLogger().info("{} v{} has loaded", Reference.APP_NAME, Reference.APP_VERSION); + + ServiceManager.schedule(new MessageService()); + getLogger().info("{} v{} has loaded", Reference.NAME, Reference.VERSION); } - public void reloadLogger() { - if (getConfig().map(Config::isDebug).orElse(false)) { + public boolean reload() { + getConfiguration().loadConfiguration(); + if (!getConfig().isPresent()) { + return false; + } + + getConfiguration().saveConfiguration(); + if (getConfig().map(Config::getGeneralCategory).map(GeneralCategory::isDebug).orElse(false)) { Configurator.setLevel(getLogger().getName(), Level.DEBUG); getLogger().debug("Debug mode enabled."); } else { Configurator.setLevel(getLogger().getName(), Level.INFO); getLogger().info("Debug mode disabled."); } + + return true; } public static DiscordMusic getInstance() { @@ -89,19 +100,11 @@ public Logger getLogger() { return logger; } - public Path getPath() { - return path; - } - public Configuration getConfiguration() { return configuration; } public Optional getConfig() { - if (getConfiguration() != null) { - return Optional.ofNullable(getConfiguration().getConfig()); - } - - return Optional.empty(); + return Optional.ofNullable(getConfiguration().getConfig()); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/Main.java b/src/main/java/io/github/lxgaming/discordmusic/Main.java index 5ef93ba..ca89fed 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/Main.java +++ b/src/main/java/io/github/lxgaming/discordmusic/Main.java @@ -21,6 +21,6 @@ public class Main { public static void main(String[] args) { Thread.currentThread().setName("Main Thread"); DiscordMusic discordMusic = new DiscordMusic(); - discordMusic.loadDiscordMusic(); + discordMusic.load(); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/ClearCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/ClearCommand.java index e7edb82..dc28e3a 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/ClearCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/ClearCommand.java @@ -37,21 +37,25 @@ public ClearCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setAuthor(message.getJDA().getSelfUser().getName(), null, message.getJDA().getSelfUser().getEffectiveAvatarUrl()); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); BlockingQueue audioQueue = AudioManager.getAudioQueue(message.getGuild()); - if (audioQueue == null || audioQueue.isEmpty()) { - embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); - embedBuilder.setTitle("Nothing queued"); + if (audioQueue == null) { + embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); + embedBuilder.setTitle("AudioQueue is unavailable"); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); return; } - audioQueue.clear(); - AudioManager.playNext(message.getGuild()); - embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); - embedBuilder.setTitle("Queue cleared"); + if (!audioQueue.isEmpty()) { + audioQueue.clear(); + AudioManager.playNext(message.getGuild()); + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); + embedBuilder.setTitle("Queue cleared"); + } else { + embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); + embedBuilder.setTitle("Nothing queued"); + } + MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/DebugCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/DebugCommand.java index fc0a708..8f55db7 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/DebugCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/DebugCommand.java @@ -18,13 +18,13 @@ import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.manager.MessageManager; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Message; import java.util.List; -import java.util.Optional; public class DebugCommand extends AbstractCommand { @@ -37,32 +37,35 @@ public DebugCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setAuthor(message.getJDA().getSelfUser().getName(), null, message.getJDA().getSelfUser().getEffectiveAvatarUrl()); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); - Optional config = DiscordMusic.getInstance().getConfig(); - if (!config.isPresent()) { + if (!arguments.isEmpty()) { embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); - embedBuilder.setTitle("Configuration error"); + embedBuilder.setTitle("Invalid arguments"); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); return; } - if (arguments.isEmpty()) { - if (config.get().isDebug()) { - config.get().setDebug(false); - DiscordMusic.getInstance().reloadLogger(); - embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); - embedBuilder.setTitle("Debugging disabled"); - MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); - return; - } - - config.get().setDebug(true); - DiscordMusic.getInstance().reloadLogger(); + GeneralCategory generalCategory = DiscordMusic.getInstance().getConfig().map(Config::getGeneralCategory).orElse(null); + if (generalCategory == null) { + embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); + embedBuilder.setTitle("GeneralCategory is unavailable"); + MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); + return; + } + + if (generalCategory.isDebug()) { + generalCategory.setDebug(false); + embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); + embedBuilder.setTitle("Debugging disabled"); + } else { + generalCategory.setDebug(true); embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); embedBuilder.setTitle("Debugging enabled"); - MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); } + + DiscordMusic.getInstance().getConfiguration().saveConfiguration(); + DiscordMusic.getInstance().reload(); + + MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/HelpCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/HelpCommand.java index b1424cf..b9f3361 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/HelpCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/HelpCommand.java @@ -16,6 +16,9 @@ package io.github.lxgaming.discordmusic.command; +import io.github.lxgaming.discordmusic.DiscordMusic; +import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.manager.CommandManager; import io.github.lxgaming.discordmusic.manager.GroupManager; @@ -26,13 +29,13 @@ import org.apache.commons.lang3.StringUtils; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; public class HelpCommand extends AbstractCommand { public HelpCommand() { addAlias("help"); + addAlias("?"); setDescription("Displays helpful information."); setPermission("help.base"); setUsage("[Command]"); @@ -44,7 +47,7 @@ public void execute(Message message, List arguments) { embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); if (arguments.isEmpty()) { - for (AbstractCommand command : CommandManager.getCommands()) { + for (AbstractCommand command : CommandManager.COMMANDS) { if (command.getAliases().isEmpty() || !GroupManager.hasPermission(message.getMember(), command.getPermission())) { continue; } @@ -60,49 +63,59 @@ public void execute(Message message, List arguments) { } embedBuilder.setTitle("Help: Index"); - embedBuilder.setFooter("<> = Required Argument, [] = Optional Argument", null); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); return; } - Optional command = CommandManager.getCommand(Toolbox.newArrayList(arguments.toArray(new String[0]))); - if (!command.isPresent()) { - embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); - embedBuilder.setTitle("No help present for " + StringUtils.join(arguments, " ")); + List childArguments = Toolbox.newArrayList(arguments.toArray(new String[0])); + AbstractCommand command = CommandManager.getCommand(childArguments).orElse(null); + if (command == null) { + embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); + embedBuilder.setTitle("Unknown command"); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); return; } - if (!GroupManager.hasPermission(message.getMember(), command.get().getPermission())) { + int index = (arguments.size() - childArguments.size()); + while (index < arguments.size()) { + arguments.remove(index); + } + + if (!GroupManager.hasPermission(message.getMember(), command.getPermission())) { embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); embedBuilder.setTitle("You do not have permission to view this command"); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); return; } - embedBuilder.setTitle("Help: " + StringUtils.capitalize(command.get().getPrimaryAlias().orElse("Unknown"))); - if (command.get().getAliases().size() > 1) { - embedBuilder.getDescriptionBuilder().append("**Aliases**: ").append(command.get().getAliases().stream().skip(1).collect(Collectors.joining(", "))); + embedBuilder.setTitle("Help: " + StringUtils.capitalize(command.getPrimaryAlias().orElse("Unknown"))); + if (command.getAliases().size() > 1) { + embedBuilder.getDescriptionBuilder().append("**Aliases**: ").append(command.getAliases().stream().skip(1).collect(Collectors.joining(", "))); embedBuilder.getDescriptionBuilder().append("\n"); } List children = Toolbox.newArrayList(); - for (AbstractCommand childCommand : command.get().getChildren()) { + for (AbstractCommand childCommand : command.getChildren()) { children.add(childCommand.getPrimaryAlias().orElse("Unknown")); } if (!children.isEmpty()) { - embedBuilder.getDescriptionBuilder().append("**Children**: ").append(StringUtils.join(children, ", ")); + embedBuilder.getDescriptionBuilder().append("**Children**: ").append(String.join(", ", children)); embedBuilder.getDescriptionBuilder().append("\n"); } embedBuilder.getDescriptionBuilder().append("**Description**: "); - embedBuilder.getDescriptionBuilder().append(StringUtils.defaultIfBlank(command.get().getDescription(), "No description provided.")).append("\n"); - embedBuilder.getDescriptionBuilder().append("**Usage**: ").append(StringUtils.join(arguments, " ")); - if (StringUtils.isNotBlank(command.get().getUsage())) { - embedBuilder.getDescriptionBuilder().append(" ").append(command.get().getUsage()); + embedBuilder.getDescriptionBuilder().append(StringUtils.defaultIfBlank(command.getDescription(), "No description provided.")).append("\n"); + embedBuilder.getDescriptionBuilder().append("**Usage**: ") + .append(DiscordMusic.getInstance().getConfig().map(Config::getGeneralCategory).map(GeneralCategory::getCommandPrefix).orElse("/")) + .append(" ") + .append(String.join(" ", arguments)); + + if (StringUtils.isNotBlank(command.getUsage())) { + embedBuilder.getDescriptionBuilder().append(" ").append(command.getUsage()); } + embedBuilder.setFooter("<> = Required Argument, [] = Optional Argument", null); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/InfoCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/InfoCommand.java index 0842fbc..a758954 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/InfoCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/InfoCommand.java @@ -16,6 +16,7 @@ package io.github.lxgaming.discordmusic.command; +import com.jagrosh.jdautilities.commons.JDAUtilitiesInfo; import com.sedmelluq.discord.lavaplayer.tools.PlayerLibrary; import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.data.Color; @@ -42,14 +43,15 @@ public InfoCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setAuthor(Reference.APP_NAME + " v" + Reference.APP_VERSION, Reference.SOURCE, message.getJDA().getSelfUser().getEffectiveAvatarUrl()); + embedBuilder.setAuthor(Reference.NAME + " v" + Reference.VERSION, Reference.SOURCE, message.getJDA().getSelfUser().getEffectiveAvatarUrl()); embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); embedBuilder.addField("Uptime", Toolbox.getTimeString(Duration.between(DiscordMusic.getInstance().getStartTime(), Instant.now()).toMillis()), false); embedBuilder.addField("Authors", Reference.AUTHORS, false); embedBuilder.addField("Source", Reference.SOURCE, false); embedBuilder.addField("Website", Reference.WEBSITE, false); embedBuilder.addField("Dependencies", "" - + "\n- " + "JDA (Java Discord API) v" + JDAInfo.VERSION + + "\n- " + "JDA v" + JDAInfo.VERSION + + "\n- " + "JDA-Utilities v" + JDAUtilitiesInfo.VERSION + "\n- " + "LavaPlayer v" + PlayerLibrary.VERSION, false); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); } diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/JoinCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/JoinCommand.java index 9e34081..bfdfed4 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/JoinCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/JoinCommand.java @@ -41,7 +41,6 @@ public JoinCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); Set voiceChannels = Toolbox.newLinkedHashSet(); if (arguments.isEmpty()) { diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/PlayCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/PlayCommand.java index 7d3fd60..2a526a4 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/PlayCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/PlayCommand.java @@ -18,11 +18,12 @@ import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; +import io.github.lxgaming.discordmusic.data.AudioTrackData; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.handler.AudioPlayerLoadResultHandler; import io.github.lxgaming.discordmusic.manager.AudioManager; import io.github.lxgaming.discordmusic.manager.MessageManager; -import io.github.lxgaming.discordmusic.util.DiscordData; import io.github.lxgaming.discordmusic.util.Toolbox; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Message; @@ -45,7 +46,7 @@ public PlayCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); + if (arguments.isEmpty()) { embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); embedBuilder.setTitle("Invalid arguments"); @@ -67,14 +68,14 @@ public void execute(Message message, List arguments) { continue; } - Optional> allowedSources = DiscordMusic.getInstance().getConfig().map(Config::getAllowedSources); + Optional> allowedSources = DiscordMusic.getInstance().getConfig().map(Config::getGeneralCategory).map(GeneralCategory::getAllowedSources); if (!allowedSources.isPresent() || !allowedSources.get().contains(url.get().getHost())) { embedBuilder.getDescriptionBuilder().append("**Forbidden:** ").append(string).append("\n"); continue; } embedBuilder.getDescriptionBuilder().append("**Processing**: ").append(string).append("\n"); - AudioManager.getAudioPlayerManager().loadItem(string, new AudioPlayerLoadResultHandler(new DiscordData(message))); + AudioManager.AUDIO_PLAYER_MANAGER.loadItem(string, new AudioPlayerLoadResultHandler(AudioTrackData.of(message))); } MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/PlayingCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/PlayingCommand.java index 5c43754..2221016 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/PlayingCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/PlayingCommand.java @@ -39,7 +39,6 @@ public PlayingCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); AudioTrack audioTrack = AudioManager.getAudioPlayer(message.getGuild()).getPlayingTrack(); if (audioTrack == null) { diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/QueueCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/QueueCommand.java index c37b926..860f9c3 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/QueueCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/QueueCommand.java @@ -38,7 +38,6 @@ public QueueCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); BlockingQueue audioQueue = AudioManager.getAudioQueue(message.getGuild()); if (audioQueue == null || audioQueue.isEmpty()) { diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/SearchCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/SearchCommand.java index 18e94a9..ab9c3e1 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/SearchCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/SearchCommand.java @@ -16,14 +16,14 @@ package io.github.lxgaming.discordmusic.command; +import io.github.lxgaming.discordmusic.data.AudioTrackData; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.handler.AudioPlayerLoadResultHandler; import io.github.lxgaming.discordmusic.manager.AudioManager; import io.github.lxgaming.discordmusic.manager.MessageManager; -import io.github.lxgaming.discordmusic.util.DiscordData; -import io.github.lxgaming.discordmusic.util.Toolbox; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.utils.MarkdownSanitizer; import org.apache.commons.lang3.StringUtils; import java.util.List; @@ -40,7 +40,6 @@ public SearchCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); if (arguments.isEmpty()) { embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); @@ -49,7 +48,7 @@ public void execute(Message message, List arguments) { return; } - String query = Toolbox.filter(String.join(" ", arguments)); + String query = String.join(" ", arguments); if (StringUtils.isBlank(query)) { embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); embedBuilder.setTitle("Invalid query"); @@ -57,10 +56,21 @@ public void execute(Message message, List arguments) { return; } - AudioManager.getAudioPlayerManager().loadItem("ytsearch: " + query, new AudioPlayerLoadResultHandler(new DiscordData(message))); + AudioManager.AUDIO_PLAYER_MANAGER.loadItem("ytsearch: " + query, new AudioPlayerLoadResultHandler(AudioTrackData.of(message))); - embedBuilder.setTitle("Search query"); - embedBuilder.appendDescription(query); + String sanitizedQuery = sanitize(query); + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); + embedBuilder.getDescriptionBuilder() + .append("**Searching for **") + .append("[").append(sanitizedQuery).append("]") + .append("(").append("https://www.youtube.com/results?search_query=").append(sanitizedQuery).append(")"); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); } + + private String sanitize(String sequence) { + return MarkdownSanitizer.sanitize(sequence) + .replace("[", "\\[").replace("]", "\\]") + .replace("(", "\\(").replace(")", "\\)") + .replace(' ', '+'); + } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/SelectCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/SelectCommand.java index 8b21ffe..fb125a4 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/SelectCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/SelectCommand.java @@ -22,13 +22,11 @@ import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.manager.AudioManager; import io.github.lxgaming.discordmusic.manager.MessageManager; -import io.github.lxgaming.discordmusic.util.DiscordData; import io.github.lxgaming.discordmusic.util.Toolbox; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Message; import java.util.List; -import java.util.Map; import java.util.Optional; public class SelectCommand extends AbstractCommand { @@ -43,7 +41,6 @@ public SelectCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); if (arguments.isEmpty()) { embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); @@ -52,7 +49,7 @@ public void execute(Message message, List arguments) { return; } - Map.Entry> searchResult = AudioManager.getSearchResult(message.getMember()); + List searchResult = AudioManager.getSearchResult(message.getMember()); if (searchResult == null) { embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); embedBuilder.setTitle("You don't have any search results pending selection."); @@ -72,16 +69,17 @@ public void execute(Message message, List arguments) { continue; } - if (selection.get() < 1 || selection.get() > searchResult.getValue().size()) { + if (selection.get() < 1 || selection.get() > searchResult.size()) { embedBuilder.getDescriptionBuilder().append("**OutOfBounds**: ").append(selection.get()); continue; } - AudioTrack audioTrack = searchResult.getValue().get(selection.get() - 1); + AudioTrack audioTrack = searchResult.get(selection.get() - 1); audioTracks.add(audioTrack); embedBuilder.getDescriptionBuilder().append("**Processing**: ").append(audioTrack.getInfo().title); } + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); embedBuilder.setTitle("Select results"); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); if (audioTracks.isEmpty()) { @@ -91,9 +89,9 @@ public void execute(Message message, List arguments) { AudioManager.removeSearchResult(message.getMember()); if (audioTracks.size() > 1) { AudioPlaylist audioPlaylist = new BasicAudioPlaylist("Search", audioTracks, null, false); - AudioManager.playlist(new DiscordData(message), audioPlaylist); + AudioManager.playlist(audioPlaylist); } else { - AudioManager.track(new DiscordData(message), audioTracks.get(0)); + AudioManager.track(audioTracks.get(0)); } } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/ShutdownCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/ShutdownCommand.java index 9a3be6a..5c24123 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/ShutdownCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/ShutdownCommand.java @@ -40,7 +40,7 @@ public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); embedBuilder.setTitle("Shutting down..."); - embedBuilder.setFooter(Toolbox.getTimeString(Duration.between(DiscordMusic.getInstance().getStartTime(), Instant.now()).toMillis()), null); + embedBuilder.setFooter("Uptime: " + Toolbox.getTimeString(Duration.between(DiscordMusic.getInstance().getStartTime(), Instant.now()).toMillis()), null); MessageManager.sendMessage(message.getChannel(), embedBuilder.build()); Runtime.getRuntime().exit(0); } diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/SkipCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/SkipCommand.java index b828dbf..4591907 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/SkipCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/SkipCommand.java @@ -36,20 +36,19 @@ public SkipCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); AudioTrack audioTrack = AudioManager.getAudioPlayer(message.getGuild()).getPlayingTrack(); - if (audioTrack == null) { + if (audioTrack != null) { + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); + embedBuilder.getDescriptionBuilder() + .append("**Skipped** ") + .append("[").append(audioTrack.getInfo().title).append("](").append(audioTrack.getInfo().uri).append(")"); + AudioManager.playNext(message.getGuild()); + } else { embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); embedBuilder.setTitle("Nothing is currently playing."); - MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); - return; } - embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); - embedBuilder.setTitle("Skipped"); - embedBuilder.getDescriptionBuilder().append("[").append(audioTrack.getInfo().title).append("](").append(audioTrack.getInfo().uri).append(")"); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); - AudioManager.playNext(message.getGuild()); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/SourcesCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/SourcesCommand.java index 4270d1a..40ceb27 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/SourcesCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/SourcesCommand.java @@ -18,12 +18,14 @@ import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.manager.MessageManager; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Message; import java.util.List; +import java.util.Set; public class SourcesCommand extends AbstractCommand { @@ -36,21 +38,21 @@ public SourcesCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); - if (!DiscordMusic.getInstance().getConfig().map(Config::getAllowedSources).isPresent()) { - embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); - embedBuilder.setTitle("Configuration error!"); - MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); - return; - } - embedBuilder.setTitle("Sources:"); - for (String source : DiscordMusic.getInstance().getConfig().map(Config::getAllowedSources).get()) { - if (embedBuilder.getDescriptionBuilder().length() != 0) { - embedBuilder.getDescriptionBuilder().append("\n"); + Set allowedSources = DiscordMusic.getInstance().getConfig().map(Config::getGeneralCategory).map(GeneralCategory::getAllowedSources).orElse(null); + if (allowedSources != null) { + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); + embedBuilder.setTitle("Sources"); + for (String source : allowedSources) { + if (embedBuilder.getDescriptionBuilder().length() != 0) { + embedBuilder.getDescriptionBuilder().append("\n"); + } + + embedBuilder.getDescriptionBuilder().append(source); } - - embedBuilder.getDescriptionBuilder().append(source); + } else { + embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); + embedBuilder.setTitle("AllowedSources is unavailable"); } MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/StopCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/StopCommand.java index 7b3868e..a9cbaff 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/StopCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/StopCommand.java @@ -36,26 +36,24 @@ public StopCommand() { @Override public void execute(Message message, List arguments) { EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); AudioPlayer audioPlayer = AudioManager.getAudioPlayer(message.getGuild()); if (audioPlayer == null) { embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); - embedBuilder.setTitle("Failed to get AudioPlayer"); + embedBuilder.setTitle("AudioPlayer is unavailable"); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); return; } - if (audioPlayer.getPlayingTrack() == null) { + if (audioPlayer.getPlayingTrack() != null) { + audioPlayer.stopTrack(); + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); + embedBuilder.setTitle("Player stopped."); + } else { embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); embedBuilder.setTitle("Player is not playing anything"); - MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); - return; } - audioPlayer.stopTrack(); - embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); - embedBuilder.setTitle("Player stopped."); MessageManager.sendTemporaryMessage(message.getChannel(), embedBuilder.build()); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/command/VolumeCommand.java b/src/main/java/io/github/lxgaming/discordmusic/command/VolumeCommand.java index 8012483..7af6086 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/command/VolumeCommand.java +++ b/src/main/java/io/github/lxgaming/discordmusic/command/VolumeCommand.java @@ -18,6 +18,7 @@ import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.manager.AudioManager; import io.github.lxgaming.discordmusic.manager.MessageManager; @@ -32,7 +33,7 @@ public class VolumeCommand extends AbstractCommand { public VolumeCommand() { addAlias("volume"); setDescription("Adjusts playback volume."); - setUsage("[0 ~ 100]"); + setUsage("[0 ~ 1000]"); setPermission("volume.base"); } @@ -54,7 +55,7 @@ public void execute(Message message, List arguments) { return; } - int maxVolume = Math.min(1000, DiscordMusic.getInstance().getConfig().map(Config::getMaxVolume).orElse(150)); + int maxVolume = Math.min(1000, DiscordMusic.getInstance().getConfig().map(Config::getGeneralCategory).map(GeneralCategory::getMaxVolume).orElse(GeneralCategory.DEFAULT_MAX_VOLUME)); if (volume < 0 || volume > maxVolume) { embedBuilder.setColor(MessageManager.getColor(Color.WARNING)); embedBuilder.setTitle("Value is outside of the allowed range (0 ~ " + maxVolume + ")"); diff --git a/src/main/java/io/github/lxgaming/discordmusic/configuration/Config.java b/src/main/java/io/github/lxgaming/discordmusic/configuration/Config.java index 39aff26..529c84d 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/configuration/Config.java +++ b/src/main/java/io/github/lxgaming/discordmusic/configuration/Config.java @@ -16,136 +16,50 @@ package io.github.lxgaming.discordmusic.configuration; +import com.google.gson.annotations.SerializedName; import io.github.lxgaming.discordmusic.configuration.category.AccountCategory; -import io.github.lxgaming.discordmusic.data.Color; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; +import io.github.lxgaming.discordmusic.configuration.category.MessageCategory; import io.github.lxgaming.discordmusic.configuration.category.ServerCategory; -import io.github.lxgaming.discordmusic.service.MessageService; +import io.github.lxgaming.discordmusic.configuration.category.ServiceCategory; import io.github.lxgaming.discordmusic.util.Toolbox; -import java.util.Map; import java.util.Set; public class Config { - private boolean debug; - private String commandPrefix; - private int defaultVolume; - private int maxVolume; - private boolean deleteInvoking; - private boolean deleteMessages; - private AccountCategory account; - private Set allowedSources; - private Set servers; - private Map colors; - private MessageService messageService; + @SerializedName("account") + private AccountCategory accountCategory = new AccountCategory(); - public Config() { - setDebug(false); - setCommandPrefix("M!"); - setDefaultVolume(25); - setMaxVolume(150); - setDeleteInvoking(true); - setDeleteMessages(true); - setAccount(new AccountCategory()); - setAllowedSources(Toolbox.newLinkedHashSet( - "bandcamp.com", // Bandcamp - "beam.pro", "mixer.com", "www.beam.pro", "www.mixer.com", // Beam - "nicovideo.jp", "www.nicovideo.jp", // Nico - "m.soundcloud.com", "soundcloud.com", "www.soundcloud.com", // SoundCloud - "go.twitch.tv", "twitch.tv", "www.twitch.tv", // Twitch - "vimeo.com", // Vimeo - "m.youtube.com", "music.youtube.com", "www.youtube.com", "youtu.be", "youtube.com" // YouTube - )); - setServers(Toolbox.newLinkedHashSet()); - setColors(Toolbox.newHashMap()); - setMessageService(new MessageService()); - } - - public boolean isDebug() { - return debug; - } - - public void setDebug(boolean debug) { - this.debug = debug; - } - - public String getCommandPrefix() { - return commandPrefix; - } - - public void setCommandPrefix(String commandPrefix) { - this.commandPrefix = commandPrefix; - } - - public int getDefaultVolume() { - return defaultVolume; - } - - public void setDefaultVolume(int defaultVolume) { - this.defaultVolume = defaultVolume; - } - - public int getMaxVolume() { - return maxVolume; - } - - public void setMaxVolume(int maxVolume) { - this.maxVolume = maxVolume; - } - - public boolean isDeleteInvoking() { - return deleteInvoking; - } - - public void setDeleteInvoking(boolean deleteInvoking) { - this.deleteInvoking = deleteInvoking; - } - - public boolean isDeleteMessages() { - return deleteMessages; - } - - public void setDeleteMessages(boolean deleteMessages) { - this.deleteMessages = deleteMessages; - } - - public AccountCategory getAccount() { - return account; - } - - public void setAccount(AccountCategory account) { - this.account = account; - } + @SerializedName("general") + private GeneralCategory generalCategory = new GeneralCategory(); - public Set getAllowedSources() { - return allowedSources; - } + @SerializedName("message") + private MessageCategory messageCategory = new MessageCategory(); - public void setAllowedSources(Set allowedSources) { - this.allowedSources = allowedSources; - } + @SerializedName("servers") + private Set serverCategories = Toolbox.newHashSet(); - public Set getServers() { - return servers; - } + @SerializedName("service") + private ServiceCategory serviceCategory = new ServiceCategory(); - public void setServers(Set servers) { - this.servers = servers; + public AccountCategory getAccountCategory() { + return accountCategory; } - public Map getColors() { - return colors; + public GeneralCategory getGeneralCategory() { + return generalCategory; } - public void setColors(Map colors) { - this.colors = colors; + public MessageCategory getMessageCategory() { + return messageCategory; } - public MessageService getMessageService() { - return messageService; + public Set getServerCategories() { + return serverCategories; } - public void setMessageService(MessageService messageService) { - this.messageService = messageService; + public ServiceCategory getServiceCategory() { + return serviceCategory; } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/configuration/Configuration.java b/src/main/java/io/github/lxgaming/discordmusic/configuration/Configuration.java index e5d31fe..fb404a5 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/configuration/Configuration.java +++ b/src/main/java/io/github/lxgaming/discordmusic/configuration/Configuration.java @@ -34,13 +34,19 @@ public class Configuration { private static final Gson GSON = new GsonBuilder() .disableHtmlEscaping() .enableComplexMapKeySerialization() + .serializeNulls() .setPrettyPrinting() .create(); + private final Path path; private Config config; + public Configuration(Path path) { + this.path = path; + } + public boolean loadConfiguration() { - Optional config = loadFile(DiscordMusic.getInstance().getPath().resolve("config.json"), Config.class); + Optional config = loadFile(this.path.resolve("config.json"), Config.class); if (config.isPresent()) { this.config = config.get(); return true; @@ -50,7 +56,7 @@ public boolean loadConfiguration() { } public boolean saveConfiguration() { - return saveFile(DiscordMusic.getInstance().getPath().resolve("config.json"), config); + return saveFile(this.path.resolve("config.json"), config); } public static Optional loadFile(Path path, Class typeOfT) { @@ -71,7 +77,7 @@ public static boolean saveFile(Path path, Object object) { public static Optional deserializeFile(Path path, Class typeOfT) { try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { - return Optional.ofNullable(getGson().fromJson(reader, typeOfT)); + return Optional.ofNullable(GSON.fromJson(reader, typeOfT)); } catch (Exception ex) { DiscordMusic.getInstance().getLogger().error("Encountered an error while deserializing {}", path, ex); return Optional.empty(); @@ -80,7 +86,7 @@ public static Optional deserializeFile(Path path, Class typeOfT) { public static boolean serializeFile(Path path, Object object) { try (Writer writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) { - getGson().toJson(object, writer); + GSON.toJson(object, writer); return true; } catch (Exception ex) { DiscordMusic.getInstance().getLogger().error("Encountered an error while serializing {}", path, ex); @@ -102,10 +108,6 @@ private static boolean createFile(Path path) { } } - public static Gson getGson() { - return GSON; - } - public Config getConfig() { return config; } diff --git a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/AccountCategory.java b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/AccountCategory.java index e4b0056..e18bd35 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/AccountCategory.java +++ b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/AccountCategory.java @@ -16,29 +16,20 @@ package io.github.lxgaming.discordmusic.configuration.category; +import io.github.lxgaming.discordmusic.util.Reference; import net.dv8tion.jda.api.OnlineStatus; import net.dv8tion.jda.api.audio.SpeakingMode; import net.dv8tion.jda.api.entities.Activity; public class AccountCategory { - private long id; - private String name; - private String token; - private String gameTitle; - private Activity.ActivityType gameType; - private OnlineStatus onlineStatus; - private SpeakingMode speakingMode; - - public AccountCategory() { - setId(0L); - setName("Unknown"); - setToken("token"); - setGameTitle("music"); - setGameType(Activity.ActivityType.DEFAULT); - setOnlineStatus(OnlineStatus.ONLINE); - setSpeakingMode(SpeakingMode.VOICE); - } + private long id = 0L; + private String name = "Unknown"; + private String token = ""; + private String activityTitle = Reference.NAME; + private Activity.ActivityType activityType = Activity.ActivityType.DEFAULT; + private OnlineStatus onlineStatus = OnlineStatus.ONLINE; + private SpeakingMode speakingMode = SpeakingMode.VOICE; public long getId() { return id; @@ -60,39 +51,19 @@ public String getToken() { return token; } - public void setToken(String token) { - this.token = token; - } - - public String getGameTitle() { - return gameTitle; - } - - public void setGameTitle(String gameTitle) { - this.gameTitle = gameTitle; + public String getActivityTitle() { + return activityTitle; } - public Activity.ActivityType getGameType() { - return gameType; - } - - public void setGameType(Activity.ActivityType gameType) { - this.gameType = gameType; + public Activity.ActivityType getActivityType() { + return activityType; } public OnlineStatus getOnlineStatus() { return onlineStatus; } - public void setOnlineStatus(OnlineStatus onlineStatus) { - this.onlineStatus = onlineStatus; - } - public SpeakingMode getSpeakingMode() { return speakingMode; } - - public void setSpeakingMode(SpeakingMode speakingMode) { - this.speakingMode = speakingMode; - } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/GeneralCategory.java b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/GeneralCategory.java new file mode 100644 index 0000000..e670e93 --- /dev/null +++ b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/GeneralCategory.java @@ -0,0 +1,83 @@ +/* + * Copyright 2019 Alex Thomson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.lxgaming.discordmusic.configuration.category; + +import io.github.lxgaming.discordmusic.util.Toolbox; + +import java.util.Set; + +public class GeneralCategory { + + public static final int DEFAULT_VOLUME = 50; + public static final int DEFAULT_MAX_VOLUME = 200; + public static final int DEFAULT_SEARCH_LIMIT = 5; + + private boolean debug = false; + private String commandPrefix = "!Music"; + private int defaultVolume = DEFAULT_VOLUME; + private int maxVolume = DEFAULT_MAX_VOLUME; + private int searchLimit = DEFAULT_SEARCH_LIMIT; + private Set allowedSources = Toolbox.newLinkedHashSet( + "bandcamp.com", // Bandcamp + "beam.pro", "mixer.com", "www.beam.pro", "www.mixer.com", // Mixer + "nicovideo.jp", "www.nicovideo.jp", // Nico + "m.soundcloud.com", "soundcloud.com", "www.soundcloud.com", // SoundCloud + "go.twitch.tv", "twitch.tv", "www.twitch.tv", // Twitch + "vimeo.com", // Vimeo + "m.youtube.com", "music.youtube.com", "www.youtube.com", "youtu.be", "youtube.com" // YouTube + ); + + public boolean isDebug() { + return debug; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public String getCommandPrefix() { + return commandPrefix; + } + + public int getDefaultVolume() { + return defaultVolume; + } + + public void setDefaultVolume(int defaultVolume) { + this.defaultVolume = defaultVolume; + } + + public int getMaxVolume() { + return maxVolume; + } + + public void setMaxVolume(int maxVolume) { + this.maxVolume = maxVolume; + } + + public int getSearchLimit() { + return searchLimit; + } + + public void setSearchLimit(int searchLimit) { + this.searchLimit = searchLimit; + } + + public Set getAllowedSources() { + return allowedSources; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/GroupCategory.java b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/GroupCategory.java index c47428c..6686d78 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/GroupCategory.java +++ b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/GroupCategory.java @@ -22,15 +22,9 @@ public class GroupCategory { - private long id; - private String name; - private Set permissions; - - public GroupCategory() { - setId(0L); - setName("Unknown"); - setPermissions(Toolbox.newLinkedHashSet()); - } + private long id = 0L; + private String name = "Unknown"; + private Set permissions = Toolbox.newHashSet(); public long getId() { return id; @@ -51,8 +45,4 @@ public void setName(String name) { public Set getPermissions() { return permissions; } - - public void setPermissions(Set permissions) { - this.permissions = permissions; - } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/MessageCategory.java b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/MessageCategory.java new file mode 100644 index 0000000..6ef2504 --- /dev/null +++ b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/MessageCategory.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Alex Thomson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.lxgaming.discordmusic.configuration.category; + +import io.github.lxgaming.discordmusic.data.Color; +import io.github.lxgaming.discordmusic.util.Toolbox; + +import java.util.Map; + +public class MessageCategory { + + private Map colors = Toolbox.newHashMap(); + private long deleteInternal = 60000L; + private boolean deleteInvoking = true; + private boolean deleteMessages = true; + + public Map getColors() { + return colors; + } + + public long getDeleteInternal() { + return deleteInternal; + } + + public boolean isDeleteInvoking() { + return deleteInvoking; + } + + public boolean isDeleteMessages() { + return deleteMessages; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/ServerCategory.java b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/ServerCategory.java index 0242465..dd08677 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/ServerCategory.java +++ b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/ServerCategory.java @@ -22,17 +22,10 @@ public class ServerCategory { - private long id; - private String name; - private long autoJoinChannel; - private Set groups; - - public ServerCategory() { - setId(0L); - setName("Unknown"); - setAutoJoinChannel(0L); - setGroups(Toolbox.newLinkedHashSet()); - } + private long id = 0L; + private String name = "Unknown"; + private long autoJoinChannel = 0L; + private Set groups = Toolbox.newHashSet(); public long getId() { return id; @@ -54,15 +47,7 @@ public long getAutoJoinChannel() { return autoJoinChannel; } - public void setAutoJoinChannel(long autoJoinChannel) { - this.autoJoinChannel = autoJoinChannel; - } - public Set getGroups() { return groups; } - - public void setGroups(Set groups) { - this.groups = groups; - } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/configuration/category/ServiceCategory.java b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/ServiceCategory.java new file mode 100644 index 0000000..4c0cc2a --- /dev/null +++ b/src/main/java/io/github/lxgaming/discordmusic/configuration/category/ServiceCategory.java @@ -0,0 +1,52 @@ +/* + * Copyright 2019 Alex Thomson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.lxgaming.discordmusic.configuration.category; + +public class ServiceCategory { + + public static final int DEFAULT_CORE_POOL_SIZE = 5; + public static final int DEFAULT_MAXIMUM_POOL_SIZE = 10; + public static final long DEFAULT_KEEP_ALIVE_TIME = 60000L; + + private int corePoolSize = DEFAULT_CORE_POOL_SIZE; + private int maximumPoolSize = DEFAULT_MAXIMUM_POOL_SIZE; + private long keepAliveTime = DEFAULT_KEEP_ALIVE_TIME; + + public int getCorePoolSize() { + return corePoolSize; + } + + public void setCorePoolSize(int corePoolSize) { + this.corePoolSize = corePoolSize; + } + + public int getMaximumPoolSize() { + return maximumPoolSize; + } + + public void setMaximumPoolSize(int maximumPoolSize) { + this.maximumPoolSize = maximumPoolSize; + } + + public long getKeepAliveTime() { + return keepAliveTime; + } + + public void setKeepAliveTime(long keepAliveTime) { + this.keepAliveTime = keepAliveTime; + } +} \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/data/AudioTrackData.java b/src/main/java/io/github/lxgaming/discordmusic/data/AudioTrackData.java new file mode 100644 index 0000000..84b5ef6 --- /dev/null +++ b/src/main/java/io/github/lxgaming/discordmusic/data/AudioTrackData.java @@ -0,0 +1,83 @@ +/* + * Copyright 2019 Alex Thomson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.lxgaming.discordmusic.data; + +import net.dv8tion.jda.api.entities.ChannelType; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageChannel; +import net.dv8tion.jda.api.entities.User; + +import java.util.Objects; + +public class AudioTrackData { + + private final Guild guild; + private final MessageChannel channel; + private final User user; + + private AudioTrackData(Guild guild, MessageChannel channel, User user) { + this.guild = guild; + this.channel = channel; + this.user = user; + } + + public static AudioTrackData of(Message message) { + if (message.isFromType(ChannelType.TEXT)) { + return new AudioTrackData(message.getGuild(), message.getChannel(), message.getAuthor()); + } else { + return new AudioTrackData(null, message.getChannel(), message.getAuthor()); + } + } + + public static AudioTrackData of(Guild guild, MessageChannel channel, User user) { + return new AudioTrackData(guild, channel, user); + } + + public Guild getGuild() { + return guild; + } + + public MessageChannel getChannel() { + return channel; + } + + public User getUser() { + return user; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + AudioTrackData data = (AudioTrackData) obj; + return Objects.equals(guild, data.guild) + && Objects.equals(channel, data.channel) + && Objects.equals(user, data.user); + } + + @Override + public int hashCode() { + return Objects.hash(guild, channel, user); + } +} \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/handler/AudioPlayerLoadResultHandler.java b/src/main/java/io/github/lxgaming/discordmusic/handler/AudioPlayerLoadResultHandler.java index cf0626d..495f2cf 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/handler/AudioPlayerLoadResultHandler.java +++ b/src/main/java/io/github/lxgaming/discordmusic/handler/AudioPlayerLoadResultHandler.java @@ -20,38 +20,40 @@ import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import io.github.lxgaming.discordmusic.data.AudioTrackData; import io.github.lxgaming.discordmusic.manager.AudioManager; -import io.github.lxgaming.discordmusic.util.DiscordData; public final class AudioPlayerLoadResultHandler implements AudioLoadResultHandler { - private final DiscordData discordData; + private final AudioTrackData trackData; - public AudioPlayerLoadResultHandler(DiscordData discordData) { - this.discordData = discordData; + public AudioPlayerLoadResultHandler(AudioTrackData trackData) { + this.trackData = trackData; } @Override public void trackLoaded(AudioTrack track) { - AudioManager.track(getDiscordData(), track); + track.setUserData(trackData); + AudioManager.track(track); } @Override public void playlistLoaded(AudioPlaylist playlist) { - AudioManager.playlist(getDiscordData(), playlist); + playlist.getTracks().forEach(track -> track.setUserData(trackData)); + if (playlist.getSelectedTrack() != null) { + playlist.getSelectedTrack().setUserData(trackData); + } + + AudioManager.playlist(playlist); } @Override public void noMatches() { - AudioManager.exception(getDiscordData(), new FriendlyException("No matches found", FriendlyException.Severity.COMMON, null)); + loadFailed(new FriendlyException("No matches found", FriendlyException.Severity.COMMON, null)); } @Override public void loadFailed(FriendlyException exception) { - AudioManager.exception(getDiscordData(), exception); - } - - private DiscordData getDiscordData() { - return discordData; + AudioManager.exception(trackData.getChannel(), exception); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/handler/AudioPlayerSendHandler.java b/src/main/java/io/github/lxgaming/discordmusic/handler/AudioPlayerSendHandler.java index fb99a61..9f828ea 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/handler/AudioPlayerSendHandler.java +++ b/src/main/java/io/github/lxgaming/discordmusic/handler/AudioPlayerSendHandler.java @@ -16,58 +16,37 @@ package io.github.lxgaming.discordmusic.handler; -import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame; -import io.github.lxgaming.discordmusic.manager.AudioManager; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; +import com.sedmelluq.discord.lavaplayer.track.playback.MutableAudioFrame; import net.dv8tion.jda.api.audio.AudioSendHandler; -import net.dv8tion.jda.api.entities.Guild; import java.nio.ByteBuffer; public final class AudioPlayerSendHandler implements AudioSendHandler { - private final Guild guild; - private AudioFrame audioFrame; + private final AudioPlayer audioPlayer; + private final ByteBuffer byteBuffer; + private final MutableAudioFrame audioFrame; - public AudioPlayerSendHandler(Guild guild) { - this.guild = guild; + public AudioPlayerSendHandler(AudioPlayer audioPlayer) { + this.audioPlayer = audioPlayer; + this.byteBuffer = ByteBuffer.allocate(1024); + this.audioFrame = new MutableAudioFrame(); + this.audioFrame.setBuffer(this.byteBuffer); } @Override public boolean canProvide() { - if (getAudioFrame() == null) { - setAudioFrame(AudioManager.getAudioPlayer(getGuild()).provide()); - } - - return getAudioFrame() != null; + return audioPlayer.provide(audioFrame); } @Override public ByteBuffer provide20MsAudio() { - try { - if (getAudioFrame() != null) { - return ByteBuffer.wrap(getAudioFrame().getData()); - } - - return null; - } finally { - setAudioFrame(null); - } + return (ByteBuffer) byteBuffer.flip(); } @Override public boolean isOpus() { return true; } - - private Guild getGuild() { - return guild; - } - - private AudioFrame getAudioFrame() { - return audioFrame; - } - - private void setAudioFrame(AudioFrame audioFrame) { - this.audioFrame = audioFrame; - } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/listener/AudioListener.java b/src/main/java/io/github/lxgaming/discordmusic/listener/AudioListener.java index 24431e7..20e2ac5 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/listener/AudioListener.java +++ b/src/main/java/io/github/lxgaming/discordmusic/listener/AudioListener.java @@ -22,8 +22,8 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; import io.github.lxgaming.discordmusic.DiscordMusic; +import io.github.lxgaming.discordmusic.data.AudioTrackData; import io.github.lxgaming.discordmusic.manager.AudioManager; -import io.github.lxgaming.discordmusic.util.DiscordData; public class AudioListener extends AudioEventAdapter { @@ -46,19 +46,21 @@ public void onTrackStart(AudioPlayer player, AudioTrack track) { public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { DiscordMusic.getInstance().getLogger().debug("Track end - {} - {} ({})", endReason.name(), track.getInfo().title, track.getInfo().uri); if (endReason.mayStartNext) { - AudioManager.playNext(track.getUserData(DiscordData.class)); + AudioManager.getData(track).map(AudioTrackData::getGuild).ifPresent(AudioManager::playNext); } } @Override public void onTrackException(AudioPlayer player, AudioTrack track, FriendlyException exception) { DiscordMusic.getInstance().getLogger().debug("Track exception - {} - {} ({})", exception.getMessage(), track.getInfo().title, track.getInfo().uri); - AudioManager.exception(track.getUserData(DiscordData.class), exception); + AudioManager.getData(track).map(AudioTrackData::getChannel).ifPresent(channel -> AudioManager.exception(channel, exception)); } @Override public void onTrackStuck(AudioPlayer player, AudioTrack track, long thresholdMs) { DiscordMusic.getInstance().getLogger().debug("Track stuck - {} ({})", track.getInfo().title, track.getInfo().uri); - AudioManager.exception(track.getUserData(DiscordData.class), new FriendlyException("Track stuck", FriendlyException.Severity.COMMON, null)); + AudioManager.getData(track).map(AudioTrackData::getChannel).ifPresent(channel -> { + AudioManager.exception(channel, new FriendlyException("Track stuck", FriendlyException.Severity.COMMON, null)); + }); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/listener/DiscordListener.java b/src/main/java/io/github/lxgaming/discordmusic/listener/DiscordListener.java index 94ac399..3e8e682 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/listener/DiscordListener.java +++ b/src/main/java/io/github/lxgaming/discordmusic/listener/DiscordListener.java @@ -18,13 +18,14 @@ import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; import io.github.lxgaming.discordmusic.DiscordMusic; +import io.github.lxgaming.discordmusic.configuration.Config; import io.github.lxgaming.discordmusic.configuration.category.AccountCategory; import io.github.lxgaming.discordmusic.configuration.category.ServerCategory; -import io.github.lxgaming.discordmusic.manager.AccountManager; import io.github.lxgaming.discordmusic.manager.AudioManager; import io.github.lxgaming.discordmusic.manager.CommandManager; import io.github.lxgaming.discordmusic.manager.GroupManager; import io.github.lxgaming.discordmusic.manager.MessageManager; +import io.github.lxgaming.discordmusic.manager.ServiceManager; import io.github.lxgaming.discordmusic.util.Toolbox; import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Guild; @@ -44,24 +45,28 @@ public class DiscordListener extends ListenerAdapter { @Override public void onReady(ReadyEvent event) { - AccountCategory account = AccountManager.getAccount().orElse(null); - if (account != null) { + AccountCategory accountCategory = DiscordMusic.getInstance().getConfig().map(Config::getAccountCategory).orElse(null); + if (accountCategory != null) { long id = event.getJDA().getSelfUser().getIdLong(); String name = Toolbox.filter(event.getJDA().getSelfUser().getName()); - if (account.getId() != id || !StringUtils.equals(account.getName(), name)) { - DiscordMusic.getInstance().getLogger().info("Account {} ({}) -> {} ({})", account.getName(), account.getId(), name, id); - account.setId(id); - account.setName(name); + if (accountCategory.getId() != id || !StringUtils.equals(accountCategory.getName(), name)) { + DiscordMusic.getInstance().getLogger().info("Account {} ({}) -> {} ({})", accountCategory.getName(), accountCategory.getId(), name, id); + accountCategory.setId(id); + accountCategory.setName(name); DiscordMusic.getInstance().getConfiguration().saveConfiguration(); } } - AudioSourceManagers.registerRemoteSources(AudioManager.getAudioPlayerManager()); + AudioSourceManagers.registerRemoteSources(AudioManager.AUDIO_PLAYER_MANAGER); for (Guild guild : event.getJDA().getGuilds()) { - AudioManager.registerAudioPlayer(guild); - GroupManager.registerServer(guild); - GroupManager.getServer(guild).map(ServerCategory::getAutoJoinChannel).map(guild::getVoiceChannelById).ifPresent(guild.getAudioManager()::openAudioConnection); + AudioManager.register(guild); + GroupManager.register(guild); + GroupManager.getServer(guild) + .map(ServerCategory::getAutoJoinChannel) + .filter(id -> id > 0) + .map(guild::getVoiceChannelById) + .ifPresent(guild.getAudioManager()::openAudioConnection); } } @@ -72,7 +77,7 @@ public void onMessageReceived(MessageReceivedEvent event) { } if (event.isFromType(ChannelType.TEXT)) { - CommandManager.process(event.getMessage()); + ServiceManager.schedule(() -> CommandManager.execute(event.getMessage())); } } @@ -88,12 +93,12 @@ public void onMessageBulkDelete(MessageBulkDeleteEvent event) { @Override public void onGuildJoin(GuildJoinEvent event) { - AudioManager.registerAudioPlayer(event.getGuild()); + AudioManager.register(event.getGuild()); } @Override public void onGuildLeave(GuildLeaveEvent event) { - AudioManager.unregisterAudioPlayer(event.getGuild()); + AudioManager.unregister(event.getGuild()); } @Override diff --git a/src/main/java/io/github/lxgaming/discordmusic/manager/AccountManager.java b/src/main/java/io/github/lxgaming/discordmusic/manager/AccountManager.java index 55f7983..80b9790 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/manager/AccountManager.java +++ b/src/main/java/io/github/lxgaming/discordmusic/manager/AccountManager.java @@ -16,6 +16,7 @@ package io.github.lxgaming.discordmusic.manager; +import com.jagrosh.jdautilities.commons.waiter.EventWaiter; import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.configuration.Config; import io.github.lxgaming.discordmusic.configuration.category.AccountCategory; @@ -23,53 +24,75 @@ import net.dv8tion.jda.api.AccountType; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.OnlineStatus; import net.dv8tion.jda.api.entities.Activity; import org.apache.commons.lang3.StringUtils; -import javax.security.auth.login.LoginException; import java.util.Optional; public class AccountManager { + public static final EventWaiter EVENT_WAITER = new EventWaiter(ServiceManager.SCHEDULED_EXECUTOR_SERVICE, false); private static JDA jda; - public static void buildAccount() { - getAccount().ifPresent(AccountManager::createJDA); + public static void prepare() { + AccountCategory accountCategory = DiscordMusic.getInstance().getConfig().map(Config::getAccountCategory).orElseThrow(NullPointerException::new); + createJDA(accountCategory.getToken()); + reload(); } - public static void reloadAccount() { - AccountCategory account = getAccount().orElse(null); + public static boolean reload() { + AccountCategory accountCategory = DiscordMusic.getInstance().getConfig().map(Config::getAccountCategory).orElse(null); + if (accountCategory == null) { + DiscordMusic.getInstance().getLogger().warn("AccountCategory is unavailable"); + return false; + } + JDA jda = getJDA().orElse(null); - if (account == null || jda == null) { - return; + if (jda == null) { + DiscordMusic.getInstance().getLogger().warn("JDA is unavailable"); + return false; } - if (account.getGameType() != null && StringUtils.isNotBlank(account.getGameTitle())) { - jda.getPresence().setActivity(Activity.of(account.getGameType(), account.getGameTitle())); + Activity activity; + if (StringUtils.isNotBlank(accountCategory.getActivityTitle()) && accountCategory.getActivityType() != null) { + activity = Activity.of(accountCategory.getActivityType(), accountCategory.getActivityTitle()); + } else { + activity = null; } - if (account.getOnlineStatus() != null) { - jda.getPresence().setStatus(account.getOnlineStatus()); + OnlineStatus onlineStatus; + if (accountCategory.getOnlineStatus() != OnlineStatus.UNKNOWN) { + onlineStatus = accountCategory.getOnlineStatus(); + } else { + onlineStatus = null; } + + jda.getPresence().setPresence(onlineStatus, activity); + return true; } - private static void createJDA(AccountCategory account) { + public static void shutdown() { + getJDA().ifPresent(JDA::shutdown); + } + + private static void createJDA(String token) { try { + if (StringUtils.isBlank(token)) { + throw new IllegalArgumentException("Token cannot be blank"); + } + JDABuilder jdaBuilder = new JDABuilder(AccountType.BOT); - jdaBuilder.addEventListeners(new DiscordListener()); + jdaBuilder.addEventListeners(EVENT_WAITER, new DiscordListener()); jdaBuilder.setBulkDeleteSplittingEnabled(false); jdaBuilder.setEnableShutdownHook(false); - jdaBuilder.setToken(account.getToken()); + jdaBuilder.setToken(token); jda = jdaBuilder.build(); - } catch (LoginException | RuntimeException ex) { - DiscordMusic.getInstance().getLogger().error("Encountered an error processing {}::createJDA", "AccountManager", ex); + } catch (Exception ex) { + DiscordMusic.getInstance().getLogger().error("Encountered an error while creating JDA", ex); } } - public static Optional getAccount() { - return DiscordMusic.getInstance().getConfig().map(Config::getAccount); - } - public static Optional getJDA() { return Optional.ofNullable(jda); } diff --git a/src/main/java/io/github/lxgaming/discordmusic/manager/AudioManager.java b/src/main/java/io/github/lxgaming/discordmusic/manager/AudioManager.java index c7ef9c8..544ceb0 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/manager/AudioManager.java +++ b/src/main/java/io/github/lxgaming/discordmusic/manager/AudioManager.java @@ -16,6 +16,7 @@ package io.github.lxgaming.discordmusic.manager; +import com.jagrosh.jdautilities.menu.OrderedMenu; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; @@ -24,55 +25,87 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.configuration.Config; -import io.github.lxgaming.discordmusic.configuration.category.AccountCategory; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; +import io.github.lxgaming.discordmusic.data.AudioTrackData; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.handler.AudioPlayerSendHandler; import io.github.lxgaming.discordmusic.listener.AudioListener; -import io.github.lxgaming.discordmusic.util.DiscordData; +import io.github.lxgaming.discordmusic.menu.CustomMenu; import io.github.lxgaming.discordmusic.util.Toolbox; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.audio.SpeakingMode; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageChannel; import org.apache.commons.lang3.StringUtils; -import java.security.InvalidParameterException; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.BlockingQueue; public class AudioManager { - private static final AudioPlayerManager AUDIO_PLAYER_MANAGER = new DefaultAudioPlayerManager(); + public static final AudioPlayerManager AUDIO_PLAYER_MANAGER = new DefaultAudioPlayerManager(); + private static final AudioListener AUDIO_LISTENER = new AudioListener(); private static final Map AUDIO_PLAYERS = Collections.synchronizedMap(Toolbox.newHashMap()); private static final Map> AUDIO_QUEUES = Collections.synchronizedMap(Toolbox.newHashMap()); - private static final Map>> SEARCH_RESULTS = Collections.synchronizedMap(Toolbox.newHashMap()); + private static final Map>> SEARCH_RESULTS = Collections.synchronizedMap(Toolbox.newHashMap()); - public static void registerAudioPlayer(Guild guild) { - if (getAudioPlayers().containsKey(guild.getIdLong()) || getAudioQueues().containsKey(guild.getIdLong()) || getSearchResults().containsKey(guild.getIdLong())) { + public static void prepare() { + GeneralCategory generalCategory = DiscordMusic.getInstance().getConfig().map(Config::getGeneralCategory).orElseThrow(NullPointerException::new); + if (generalCategory.getMaxVolume() < 0) { + DiscordMusic.getInstance().getLogger().warn("MaxVolume is out of bounds. Resetting to {}", GeneralCategory.DEFAULT_MAX_VOLUME); + // Discord limit + generalCategory.setMaxVolume(GeneralCategory.DEFAULT_MAX_VOLUME); + } else if (generalCategory.getMaxVolume() > 1000) { + DiscordMusic.getInstance().getLogger().warn("MaxVolume is out of bounds. Resetting to {}", 1000); + // LavaPlayer limit - DefaultAudioPlayer::setVolume + generalCategory.setMaxVolume(1000); + } + + if (generalCategory.getDefaultVolume() < 0 || generalCategory.getDefaultVolume() > generalCategory.getMaxVolume()) { + DiscordMusic.getInstance().getLogger().warn("DefaultVolume is out of bounds. Resetting to {}", GeneralCategory.DEFAULT_VOLUME); + generalCategory.setDefaultVolume(GeneralCategory.DEFAULT_VOLUME); + } + + if (generalCategory.getSearchLimit() < 0 || generalCategory.getSearchLimit() > 10) { + DiscordMusic.getInstance().getLogger().warn("SearchLimit is out of bounds. Resetting to {}", GeneralCategory.DEFAULT_SEARCH_LIMIT); + generalCategory.setDefaultVolume(GeneralCategory.DEFAULT_SEARCH_LIMIT); + } + } + + public static void register(Guild guild) { + if (AUDIO_PLAYERS.containsKey(guild.getIdLong())) { DiscordMusic.getInstance().getLogger().warn("{} ({}) AudioPlayer is already registered", guild.getName(), guild.getIdLong()); return; } - if (!(guild.getAudioManager().getSendingHandler() instanceof AudioPlayerSendHandler)) { - guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(guild)); - } + AudioPlayer audioPlayer = AUDIO_PLAYER_MANAGER.createPlayer(); + audioPlayer.addListener(AUDIO_LISTENER); + guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(audioPlayer)); - guild.getAudioManager().setSpeakingMode(AccountManager.getAccount().map(AccountCategory::getSpeakingMode).orElse(SpeakingMode.VOICE)); + Config config = DiscordMusic.getInstance().getConfig().orElse(null); + if (config != null) { + audioPlayer.setVolume(Math.min(config.getGeneralCategory().getDefaultVolume(), config.getGeneralCategory().getMaxVolume())); + guild.getAudioManager().setSpeakingMode(config.getAccountCategory().getSpeakingMode()); + } else { + audioPlayer.setVolume(GeneralCategory.DEFAULT_VOLUME); + guild.getAudioManager().setSpeakingMode(SpeakingMode.VOICE); + } - AudioPlayer audioPlayer = getAudioPlayerManager().createPlayer(); - audioPlayer.addListener(new AudioListener()); - audioPlayer.setVolume(Math.min(DiscordMusic.getInstance().getConfig().map(Config::getMaxVolume).orElse(150), DiscordMusic.getInstance().getConfig().map(Config::getDefaultVolume).orElse(50))); - getAudioPlayers().put(guild.getIdLong(), audioPlayer); - getAudioQueues().put(guild.getIdLong(), Toolbox.newLinkedBlockingQueue()); - getSearchResults().put(guild.getIdLong(), Toolbox.newHashMap()); + AUDIO_PLAYERS.put(guild.getIdLong(), audioPlayer); + AUDIO_QUEUES.put(guild.getIdLong(), Toolbox.newLinkedBlockingQueue()); + SEARCH_RESULTS.put(guild.getIdLong(), Collections.synchronizedMap(Toolbox.newHashMap())); } - public static void unregisterAudioPlayer(Guild guild) { - getAudioPlayers().remove(guild.getIdLong()); - getAudioQueues().remove(guild.getIdLong()); - getSearchResults().remove(guild.getIdLong()); + public static void unregister(Guild guild) { + AUDIO_PLAYERS.remove(guild.getIdLong()); + AUDIO_QUEUES.remove(guild.getIdLong()); + SEARCH_RESULTS.remove(guild.getIdLong()); } public static boolean pause(Guild guild) { @@ -91,10 +124,6 @@ public static boolean play(Guild guild) { return true; } - public static boolean playNext(DiscordData discordData) { - return discordData != null && discordData.isValid() && playNext(discordData.getGuild()); - } - public static boolean playNext(Guild guild) { return playNext(AudioManager.getAudioPlayer(guild), getAudioQueue(guild).poll()); } @@ -105,8 +134,8 @@ public static boolean playNext(AudioPlayer audioPlayer, AudioTrack audioTrack) { return false; } - DiscordData discordData = audioTrack.getUserData(DiscordData.class); - if (discordData == null || !discordData.isValid()) { + AudioTrackData trackData = getData(audioTrack).orElse(null); + if (trackData == null) { return false; } @@ -116,7 +145,7 @@ public static boolean playNext(AudioPlayer audioPlayer, AudioTrack audioTrack) { embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); embedBuilder.setTitle("Now playing"); embedBuilder.getDescriptionBuilder().append("[").append(audioTrack.getInfo().title).append("](").append(audioTrack.getInfo().uri).append(")"); - MessageManager.sendTemporaryMessage(discordData.getMessage().getChannel(), embedBuilder.build()); + MessageManager.sendTemporaryMessage(trackData.getChannel(), embedBuilder.build()); return true; } @@ -125,140 +154,171 @@ public static boolean canPlayNext(Guild guild) { return (audioPlayer.getPlayingTrack() == null || audioPlayer.getPlayingTrack().getInfo().isStream) && guild.getAudioManager().isConnected(); } - public static void exception(DiscordData discordData, FriendlyException exception) { - if (!discordData.isValid()) { - return; - } - + public static void exception(MessageChannel channel, FriendlyException exception) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); embedBuilder.setTitle("Encountered an error"); embedBuilder.getDescriptionBuilder().append(StringUtils.defaultIfBlank(exception.getMessage(), "Unknown")); embedBuilder.setFooter("Details available in console", null); - MessageManager.sendTemporaryMessage(discordData.getMessage().getChannel(), embedBuilder.build()); + MessageManager.sendTemporaryMessage(channel, embedBuilder.build()); } - public static void playlist(DiscordData discordData, AudioPlaylist audioPlaylist) { - try { - if (!discordData.isValid()) { - throw new InvalidParameterException("DiscordData cannot be invalid"); + public static void playlist(AudioPlaylist audioPlaylist) throws IllegalArgumentException { + if (audioPlaylist.isSearchResult()) { + int searchLimit = DiscordMusic.getInstance().getConfig().map(Config::getGeneralCategory).map(GeneralCategory::getSearchLimit).orElse(GeneralCategory.DEFAULT_SEARCH_LIMIT); + Map> data = Toolbox.newHashMap(); + for (AudioTrack audioTrack : audioPlaylist.getTracks()) { + AudioTrackData audioTrackData = getData(audioTrack).orElse(null); + if (audioTrackData == null) { + DiscordMusic.getInstance().getLogger().warn("AudioTrack from AudioPlaylist is missing AudioTrackData"); + continue; + } + + data.compute(audioTrackData, (key, value) -> { + if (value != null) { + if (value.size() < searchLimit) { + value.add(audioTrack); + } + + return value; + } else { + return Toolbox.newArrayList(audioTrack); + } + }); } - EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.DEFAULT)); - if (audioPlaylist.isSearchResult()) { - List audioTracks = Toolbox.newArrayList(); - for (int index = 0; index < Math.min(audioPlaylist.getTracks().size(), 5); index++) { - AudioTrack audioTrack = audioPlaylist.getTracks().get(index); - audioTrack.setUserData(discordData); - audioTracks.add(audioTrack); + for (Map.Entry> entry : data.entrySet()) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); + + for (int index = 0; index < entry.getValue().size(); index++) { + AudioTrack audioTrack = entry.getValue().get(index); if (embedBuilder.getDescriptionBuilder().length() != 0) { embedBuilder.getDescriptionBuilder().append("\n"); } - embedBuilder.getDescriptionBuilder().append("**").append(index + 1).append(".** "); - embedBuilder.getDescriptionBuilder().append("[").append(audioTrack.getInfo().title).append("](").append(audioTrack.getInfo().uri).append(")"); + embedBuilder.getDescriptionBuilder() + .append("**").append(index + 1).append(".**") + .append(" [").append(audioTrack.getInfo().title).append("](").append(audioTrack.getInfo().uri).append(")"); } - //TODO Need to clear SearchResults after a certain amount of time has passed. - - getSearchResults().get(discordData.getGuild().getIdLong()).put(discordData, audioTracks); - embedBuilder.setTitle("Search results"); - embedBuilder.setFooter("Use " + DiscordMusic.getInstance().getConfig().map(Config::getCommandPrefix).orElse("/") + "Select [ID...]", null); - MessageManager.sendTemporaryMessage(discordData.getMessage().getChannel(), embedBuilder.build()); - return; - } - - if (audioPlaylist.getSelectedTrack() != null) { - track(discordData, audioPlaylist.getSelectedTrack()); - return; + CustomMenu.Builder menuBuilder = new CustomMenu.Builder(); + menuBuilder.addChoices(Arrays.copyOf(OrderedMenu.NUMBERS, entry.getValue().size())); + menuBuilder.addUsers(entry.getKey().getUser()); + menuBuilder.setAction(event -> { + int index = Arrays.binarySearch(OrderedMenu.NUMBERS, event.getReactionEmote().getName()); + if (index < 0 || index >= entry.getValue().size()) { + return false; + } + + AudioManager.track(entry.getValue().get(index)); + return true; + }); + menuBuilder.setFinalAction(message -> { + message.delete().queue(); + getSearchResults(message.getGuild()).remove(message); + }); + menuBuilder.setEventWaiter(AccountManager.EVENT_WAITER); + menuBuilder.build().display(entry.getKey().getChannel(), embedBuilder.build()); } + return; + } + + if (audioPlaylist.getSelectedTrack() != null) { + track(audioPlaylist.getSelectedTrack()); + return; + } + + if (!audioPlaylist.getTracks().isEmpty()) { + Map> data = Toolbox.newHashMap(); for (AudioTrack audioTrack : audioPlaylist.getTracks()) { - audioTrack.setUserData(discordData); - getAudioQueue(discordData.getGuild()).offer(audioTrack); + AudioTrackData audioTrackData = getData(audioTrack).orElse(null); + if (audioTrackData == null) { + DiscordMusic.getInstance().getLogger().warn("AudioTrack from AudioPlaylist is missing AudioTrackData"); + continue; + } + + // noinspection Convert2MethodRef + data.computeIfAbsent(audioTrackData, key -> Toolbox.newArrayList()).add(audioTrack); } - if (canPlayNext(discordData.getGuild())) { - playNext(discordData.getGuild()); + for (Map.Entry> entry : data.entrySet()) { + for (AudioTrack audioTrack : entry.getValue()) { + getAudioQueue(entry.getKey().getGuild()).offer(audioTrack); + } + + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); + embedBuilder.setTitle(entry.getValue().size() + " tracks added to queue"); + MessageManager.sendTemporaryMessage(entry.getKey().getChannel(), embedBuilder.build()); + + if (canPlayNext(entry.getKey().getGuild())) { + playNext(entry.getKey().getGuild()); + } } - embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); - embedBuilder.setTitle(audioPlaylist.getTracks().size() + " tracks added to queue"); - MessageManager.sendTemporaryMessage(discordData.getMessage().getChannel(), embedBuilder.build()); - } catch (RuntimeException ex) { - exception(discordData, new FriendlyException(ex.getMessage(), FriendlyException.Severity.COMMON, ex)); + return; } + + DiscordMusic.getInstance().getLogger().warn("Failed to handle AudioPlaylist"); } - public static void track(DiscordData discordData, AudioTrack audioTrack) { - try { - if (!discordData.isValid()) { - throw new InvalidParameterException("DiscordData cannot be invalid"); - } - - audioTrack.setUserData(discordData); - getAudioQueue(discordData.getGuild()).offer(audioTrack); - if (canPlayNext(discordData.getGuild())) { - playNext(discordData.getGuild()); - return; - } - - EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); - embedBuilder.setTitle("Track added to queue"); - embedBuilder.getDescriptionBuilder().append("[").append(audioTrack.getInfo().title).append("](").append(audioTrack.getInfo().uri).append(")"); - MessageManager.sendTemporaryMessage(discordData.getMessage().getChannel(), embedBuilder.build()); - } catch (RuntimeException ex) { - exception(discordData, new FriendlyException(ex.getMessage(), FriendlyException.Severity.COMMON, ex)); + public static void track(AudioTrack audioTrack) throws IllegalArgumentException { + AudioTrackData trackData = getData(audioTrack).orElseThrow(() -> new IllegalArgumentException("AudioTrack is missing TrackData")); + getAudioQueue(trackData.getGuild()).offer(audioTrack); + if (canPlayNext(trackData.getGuild())) { + playNext(trackData.getGuild()); + return; } + + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageManager.getColor(Color.SUCCESS)); + embedBuilder.setTitle("Track added to queue"); + embedBuilder.getDescriptionBuilder().append("[").append(audioTrack.getInfo().title).append("](").append(audioTrack.getInfo().uri).append(")"); + MessageManager.sendTemporaryMessage(trackData.getChannel(), embedBuilder.build()); } - public static AudioPlayer getAudioPlayer(Guild guild) { - return getAudioPlayers().get(guild.getIdLong()); + public static Optional getData(AudioTrack audioTrack) { + return Optional.ofNullable(audioTrack.getUserData(AudioTrackData.class)); } - public static BlockingQueue getAudioQueue(Guild guild) { - return getAudioQueues().get(guild.getIdLong()); + public static AudioPlayer getAudioPlayer(Guild guild) { + return AUDIO_PLAYERS.get(guild.getIdLong()); } - public static void removeSearchResult(Member member) { - Map.Entry> entry = getSearchResult(member); - if (entry == null) { - return; - } - - getSearchResults().get(member.getGuild().getIdLong()).remove(entry.getKey()); + public static BlockingQueue getAudioQueue(Guild guild) { + return AUDIO_QUEUES.get(guild.getIdLong()); } - public static Map.Entry> getSearchResult(Member member) { - Map> searchResults = getSearchResults().get(member.getGuild().getIdLong()); + public static List getSearchResult(Member member) { + Map> searchResults = getSearchResults(member.getGuild()); if (searchResults == null) { return null; } - for (Map.Entry> entry : searchResults.entrySet()) { - if (entry.getKey().isValid() && entry.getKey().getMessage().getAuthor().getIdLong() == member.getUser().getIdLong()) { - return entry; + // noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (searchResults) { + for (Map.Entry> entry : searchResults.entrySet()) { + if (entry.getKey().getAuthor().getIdLong() == member.getIdLong()) { + return entry.getValue(); + } } + + return null; } - - return null; - } - - public static AudioPlayerManager getAudioPlayerManager() { - return AUDIO_PLAYER_MANAGER; - } - - private static Map getAudioPlayers() { - return AUDIO_PLAYERS; } - private static Map> getAudioQueues() { - return AUDIO_QUEUES; + public static void removeSearchResult(Member member) { + Map> searchResults = getSearchResults(member.getGuild()); + if (searchResults == null) { + return; + } + + searchResults.keySet().removeIf(message -> message.getAuthor().getIdLong() == member.getIdLong()); } - private static Map>> getSearchResults() { - return SEARCH_RESULTS; + public static Map> getSearchResults(Guild guild) { + return SEARCH_RESULTS.get(guild.getIdLong()); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/manager/CommandManager.java b/src/main/java/io/github/lxgaming/discordmusic/manager/CommandManager.java index 33ab110..cb03f4b 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/manager/CommandManager.java +++ b/src/main/java/io/github/lxgaming/discordmusic/manager/CommandManager.java @@ -34,6 +34,8 @@ import io.github.lxgaming.discordmusic.command.StopCommand; import io.github.lxgaming.discordmusic.command.VolumeCommand; import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.GeneralCategory; +import io.github.lxgaming.discordmusic.configuration.category.MessageCategory; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.util.Toolbox; import net.dv8tion.jda.api.EmbedBuilder; @@ -46,10 +48,10 @@ public class CommandManager { - private static final Set COMMANDS = Toolbox.newLinkedHashSet(); - private static final Set> COMMAND_CLASSES = Toolbox.newLinkedHashSet(); + public static final Set COMMANDS = Toolbox.newHashSet(); + private static final Set> COMMAND_CLASSES = Toolbox.newHashSet(); - public static void buildCommands() { + public static void prepare() { registerCommand(ClearCommand.class); registerCommand(DebugCommand.class); registerCommand(HelpCommand.class); @@ -67,68 +69,58 @@ public static void buildCommands() { registerCommand(VolumeCommand.class); } - public static boolean process(Message message) { + public static boolean execute(Message message) { List arguments = getArguments(MessageManager.getMessageContent(message)).map(Toolbox::newArrayList).orElse(null); if (arguments == null || arguments.isEmpty()) { return false; } - Optional command = getCommand(arguments); - if (!command.isPresent()) { + AbstractCommand command = getCommand(arguments).orElse(null); + if (command == null) { return false; } - if (DiscordMusic.getInstance().getConfig().map(Config::isDeleteInvoking).orElse(false)) { - MessageManager.getMessages().add(message); + if (DiscordMusic.getInstance().getConfig().map(Config::getMessageCategory).map(MessageCategory::isDeleteInvoking).orElse(false)) { + MessageManager.MESSAGES.add(message); } - if (StringUtils.isBlank(command.get().getPermission()) || !GroupManager.hasPermission(message.getMember(), command.get().getPermission())) { + if (StringUtils.isBlank(command.getPermission()) || !GroupManager.hasPermission(message.getMember(), command.getPermission())) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); embedBuilder.setTitle("You do not have permission to execute this command"); - embedBuilder.setFooter("Missing permission: " + command.get().getPermission(), null); + embedBuilder.setFooter("Missing permission: " + command.getPermission(), null); MessageManager.sendTemporaryMessage(message.getTextChannel(), embedBuilder.build()); return false; } - DiscordMusic.getInstance().getLogger().debug("Processing {} for {}", command.get().getPrimaryAlias().orElse("Unknown"), GroupManager.getUsername(message.getMember().getUser())); + if (!arguments.isEmpty()) { + DiscordMusic.getInstance().getLogger().debug("Processing {} {} for {}", + command.getPrimaryAlias().orElse("Unknown"), String.join(" ", arguments), + GroupManager.getUsername(message.getAuthor())); + } else { + DiscordMusic.getInstance().getLogger().debug("Processing {} for {}", + command.getPrimaryAlias().orElse("Unknown"), + GroupManager.getUsername(message.getAuthor())); + } try { - command.get().execute(message, arguments); + command.execute(message, arguments); + return true; } catch (Exception ex) { - DiscordMusic.getInstance().getLogger().error("Encountered an error processing {}::process", "CommandManager", ex); + DiscordMusic.getInstance().getLogger().error("Encountered an error while executing {}", command.getClass().getSimpleName(), ex); EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageManager.getColor(Color.ERROR)); embedBuilder.setTitle("An error has occurred. Details are available in console."); embedBuilder.appendDescription(Toolbox.filter(MessageManager.getMessageContent(message))); embedBuilder.setFooter("Exception: " + ex.getClass().getSimpleName(), null); MessageManager.sendMessage(message.getTextChannel(), embedBuilder.build()); - } - - return true; - } - - public static boolean registerCommand(Class commandClass) { - if (getCommandClasses().contains(commandClass)) { - DiscordMusic.getInstance().getLogger().warn("{} has already been registered", commandClass.getSimpleName()); return false; } - - getCommandClasses().add(commandClass); - Optional command = Toolbox.newInstance(commandClass); - if (!command.isPresent()) { - DiscordMusic.getInstance().getLogger().error("{} failed to initialize", commandClass.getSimpleName()); - return false; - } - - getCommands().add(command.get()); - DiscordMusic.getInstance().getLogger().debug("{} registered", commandClass.getSimpleName()); - return true; } public static boolean registerAlias(AbstractCommand command, String alias) { if (Toolbox.containsIgnoreCase(command.getAliases(), alias)) { - DiscordMusic.getInstance().getLogger().warn("{} has already been registered for {}", alias, command.getClass().getSimpleName()); + DiscordMusic.getInstance().getLogger().warn("{} is already registered for {}", alias, command.getClass().getSimpleName()); return false; } @@ -137,27 +129,43 @@ public static boolean registerAlias(AbstractCommand command, String alias) { return true; } + public static boolean registerCommand(Class commandClass) { + if (registerCommand(COMMANDS, commandClass)) { + DiscordMusic.getInstance().getLogger().debug("{} registered", commandClass.getSimpleName()); + return true; + } else { + return false; + } + } + public static boolean registerCommand(AbstractCommand parentCommand, Class commandClass) { if (parentCommand.getClass() == commandClass) { DiscordMusic.getInstance().getLogger().warn("{} attempted to register itself", parentCommand.getClass().getSimpleName()); return false; } - if (getCommandClasses().contains(commandClass)) { - DiscordMusic.getInstance().getLogger().warn("{} has already been registered", commandClass.getSimpleName()); + if (registerCommand(parentCommand.getChildren(), commandClass)) { + DiscordMusic.getInstance().getLogger().debug("{} registered for {}", commandClass.getSimpleName(), parentCommand.getClass().getSimpleName()); + return true; + } else { + return false; + } + } + + private static boolean registerCommand(Set commands, Class commandClass) { + if (COMMAND_CLASSES.contains(commandClass)) { + DiscordMusic.getInstance().getLogger().warn("{} is already registered", commandClass.getSimpleName()); return false; } - getCommandClasses().add(commandClass); - Optional command = Toolbox.newInstance(commandClass); - if (!command.isPresent()) { + COMMAND_CLASSES.add(commandClass); + AbstractCommand command = Toolbox.newInstance(commandClass).orElse(null); + if (command == null) { DiscordMusic.getInstance().getLogger().error("{} failed to initialize", commandClass.getSimpleName()); return false; } - parentCommand.getChildren().add(command.get()); - DiscordMusic.getInstance().getLogger().debug("{} registered for {}", commandClass.getSimpleName(), parentCommand.getClass().getSimpleName()); - return true; + return commands.add(command); } public static Optional getCommand(List arguments) { @@ -169,7 +177,7 @@ private static Optional getCommand(AbstractCommand parentComman if (parentCommand != null) { commands.addAll(parentCommand.getChildren()); } else { - commands.addAll(getCommands()); + commands.addAll(COMMANDS); } if (arguments.isEmpty() || commands.isEmpty()) { @@ -187,7 +195,7 @@ private static Optional getCommand(AbstractCommand parentComman } private static Optional getArguments(String message) { - String commandPrefix = DiscordMusic.getInstance().getConfig().map(Config::getCommandPrefix).orElse("/"); + String commandPrefix = DiscordMusic.getInstance().getConfig().map(Config::getGeneralCategory).map(GeneralCategory::getCommandPrefix).orElse("/"); if (StringUtils.startsWithIgnoreCase(message, commandPrefix)) { return Optional.ofNullable(StringUtils.split(Toolbox.filter(StringUtils.removeStartIgnoreCase(message, commandPrefix)), " ")); } @@ -198,12 +206,4 @@ private static Optional getArguments(String message) { return Optional.empty(); } - - public static Set getCommands() { - return COMMANDS; - } - - private static Set> getCommandClasses() { - return COMMAND_CLASSES; - } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/manager/GroupManager.java b/src/main/java/io/github/lxgaming/discordmusic/manager/GroupManager.java index 90948aa..dd6eedc 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/manager/GroupManager.java +++ b/src/main/java/io/github/lxgaming/discordmusic/manager/GroupManager.java @@ -32,7 +32,7 @@ public class GroupManager { - public static void registerServer(Guild guild) { + public static void register(Guild guild) { Set groups = Toolbox.newLinkedHashSet(); for (Role role : guild.getRoles()) { GroupCategory group = getGroup(role).orElse(new GroupCategory()); @@ -41,12 +41,13 @@ public static void registerServer(Guild guild) { groups.add(group); } - ServerCategory server = getServer(guild).orElse(new ServerCategory()); - server.setId(guild.getIdLong()); - server.setName(guild.getName()); - server.setGroups(groups); + ServerCategory serverCategory = getServer(guild).orElse(new ServerCategory()); + serverCategory.setId(guild.getIdLong()); + serverCategory.setName(guild.getName()); + serverCategory.getGroups().clear(); + serverCategory.getGroups().addAll(groups); - DiscordMusic.getInstance().getConfig().map(Config::getServers).ifPresent(servers -> servers.add(server)); + DiscordMusic.getInstance().getConfig().map(Config::getServerCategories).ifPresent(serverCategories -> serverCategories.add(serverCategory)); DiscordMusic.getInstance().getConfiguration().saveConfiguration(); } @@ -86,12 +87,12 @@ public static String getUsername(User user) { } public static Optional getGroup(Role role) { - ServerCategory server = getServer(role.getGuild()).orElse(null); - if (server == null || server.getGroups().isEmpty()) { + ServerCategory serverCategory = getServer(role.getGuild()).orElse(null); + if (serverCategory == null || serverCategory.getGroups().isEmpty()) { return Optional.empty(); } - for (GroupCategory group : server.getGroups()) { + for (GroupCategory group : serverCategory.getGroups()) { if (group.getId() == role.getIdLong()) { return Optional.of(group); } @@ -112,12 +113,12 @@ public static Set getGroups(Member member) { } public static Optional getServer(Guild guild) { - Set servers = DiscordMusic.getInstance().getConfig().map(Config::getServers).orElse(null); - if (servers == null || servers.isEmpty()) { + Set serverCategories = DiscordMusic.getInstance().getConfig().map(Config::getServerCategories).orElse(null); + if (serverCategories == null || serverCategories.isEmpty()) { return Optional.empty(); } - for (ServerCategory server : servers) { + for (ServerCategory server : serverCategories) { if (server.getId() == guild.getIdLong()) { return Optional.of(server); } diff --git a/src/main/java/io/github/lxgaming/discordmusic/manager/MessageManager.java b/src/main/java/io/github/lxgaming/discordmusic/manager/MessageManager.java index a613192..8c2f6e6 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/manager/MessageManager.java +++ b/src/main/java/io/github/lxgaming/discordmusic/manager/MessageManager.java @@ -18,12 +18,14 @@ import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.MessageCategory; import io.github.lxgaming.discordmusic.data.Color; import io.github.lxgaming.discordmusic.util.Toolbox; import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.MessageChannel; import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.exceptions.VerificationLevelException; import net.dv8tion.jda.internal.entities.DataMessage; @@ -32,51 +34,46 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.function.Consumer; public class MessageManager { - private static final List MESSAGES = Collections.synchronizedList(Toolbox.newArrayList()); + public static final List MESSAGES = Collections.synchronizedList(Toolbox.newArrayList()); - public static void buildColors() { - Map colors = DiscordMusic.getInstance().getConfig().map(Config::getColors).orElse(null); - if (colors == null) { - return; - } - - colors.putIfAbsent(Color.ERROR, "#C13737"); - colors.putIfAbsent(Color.SUCCESS, "#46A84B"); - colors.putIfAbsent(Color.WARNING, "#EAA245"); + public static void prepare() { + MessageCategory messageCategory = DiscordMusic.getInstance().getConfig().map(Config::getMessageCategory).orElseThrow(NullPointerException::new); + messageCategory.getColors().putIfAbsent(Color.ERROR, "#C13737"); + messageCategory.getColors().putIfAbsent(Color.SUCCESS, "#46A84B"); + messageCategory.getColors().putIfAbsent(Color.WARNING, "#EAA245"); for (Color color : Color.values()) { - colors.putIfAbsent(color, "#7289DA"); + messageCategory.getColors().putIfAbsent(color, "#7289DA"); // Blurple } } - public static void sendMessage(MessageChannel messageChannel, MessageEmbed messageEmbed) { - sendMessage(messageChannel, new MessageBuilder().setEmbed(messageEmbed).build()); + public static void sendTemporaryMessage(MessageChannel channel, MessageEmbed messageEmbed) { + sendTemporaryMessage(channel, new MessageBuilder().setEmbed(messageEmbed).build()); } - public static void sendTemporaryMessage(MessageChannel messageChannel, MessageEmbed messageEmbed) { - sendTemporaryMessage(messageChannel, new MessageBuilder().setEmbed(messageEmbed).build()); + public static void sendTemporaryMessage(MessageChannel channel, Message message) { + sendMessage(channel, message, success -> { + if (DiscordMusic.getInstance().getConfig().map(Config::getMessageCategory).map(MessageCategory::isDeleteMessages).orElse(false)) { + MESSAGES.add(success); + } + }); } - public static void sendMessage(MessageChannel messageChannel, Message message) { - sendMessage(messageChannel, message, success -> { - }); + public static void sendMessage(MessageChannel channel, MessageEmbed messageEmbed) { + sendMessage(channel, new MessageBuilder().setEmbed(messageEmbed).build()); } - public static void sendTemporaryMessage(MessageChannel messageChannel, Message message) { - sendMessage(messageChannel, message, success -> { - if (DiscordMusic.getInstance().getConfig().map(Config::isDeleteMessages).orElse(false)) { - getMessages().add(success); - } + public static void sendMessage(MessageChannel channel, Message message) { + sendMessage(channel, message, success -> { }); } public static void sendMessage(MessageChannel messageChannel, Message message, Consumer success) { - sendMessage(messageChannel, message, success, failure -> DiscordMusic.getInstance().getLogger().error("Encountered an error processing {}::sendMessage", "MessageManager", failure)); + sendMessage(messageChannel, message, success, failure -> DiscordMusic.getInstance().getLogger().error("Encountered an error while sending message", failure)); } public static void sendMessage(MessageChannel messageChannel, Message message, Consumer success, Consumer failure) { @@ -88,7 +85,12 @@ public static void sendMessage(MessageChannel messageChannel, Message message, C } public static int getColor(Color color) { - return DiscordMusic.getInstance().getConfig().map(Config::getColors).map(colors -> colors.get(color)).map(NumberUtils::createInteger).orElse(0); + return DiscordMusic.getInstance().getConfig() + .map(Config::getMessageCategory) + .map(MessageCategory::getColors) + .map(colors -> colors.get(color)) + .map(NumberUtils::createInteger) + .orElse(Role.DEFAULT_COLOR_RAW); } public static String getMessageContent(Message message) { @@ -100,10 +102,6 @@ public static String getMessageContent(Message message) { } public static void removeMessages(Collection messages) { - getMessages().removeIf(message -> messages.contains(message.getId())); - } - - public static List getMessages() { - return MESSAGES; + MESSAGES.removeIf(message -> messages.contains(message.getId())); } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/manager/ServiceManager.java b/src/main/java/io/github/lxgaming/discordmusic/manager/ServiceManager.java index a64db36..8870405 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/manager/ServiceManager.java +++ b/src/main/java/io/github/lxgaming/discordmusic/manager/ServiceManager.java @@ -18,41 +18,84 @@ import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.ServiceCategory; import io.github.lxgaming.discordmusic.service.AbstractService; import io.github.lxgaming.discordmusic.util.Toolbox; import java.util.Optional; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ServiceManager { - private static final ScheduledExecutorService SCHEDULED_EXECUTOR_SERVICE = Executors.newScheduledThreadPool(10, Toolbox.buildThreadFactory("Service Thread #%d")); + public static final ScheduledThreadPoolExecutor SCHEDULED_EXECUTOR_SERVICE = new ScheduledThreadPoolExecutor(0, Toolbox.newThreadFactory("Service Thread #%d")); - public static void buildServices() { - DiscordMusic.getInstance().getConfig().map(Config::getMessageService).ifPresent(ServiceManager::schedule); + public static void prepare() { + ServiceCategory serviceCategory = DiscordMusic.getInstance().getConfig().map(Config::getServiceCategory).orElseThrow(NullPointerException::new); + if (serviceCategory.getCorePoolSize() < 0) { + DiscordMusic.getInstance().getLogger().warn("CorePoolSize is out of bounds. Resetting to {}", ServiceCategory.DEFAULT_CORE_POOL_SIZE); + serviceCategory.setCorePoolSize(ServiceCategory.DEFAULT_CORE_POOL_SIZE); + } + + if (serviceCategory.getMaximumPoolSize() < serviceCategory.getCorePoolSize()) { + DiscordMusic.getInstance().getLogger().warn("MaximumPoolSize is out of bounds. Resetting to {}", ServiceCategory.DEFAULT_MAXIMUM_POOL_SIZE); + serviceCategory.setMaximumPoolSize(ServiceCategory.DEFAULT_MAXIMUM_POOL_SIZE); + } + + if (serviceCategory.getKeepAliveTime() <= 0) { + DiscordMusic.getInstance().getLogger().warn("KeepAliveTime is out of bounds. Resetting to {}", ServiceCategory.DEFAULT_KEEP_ALIVE_TIME); + serviceCategory.setKeepAliveTime(ServiceCategory.DEFAULT_KEEP_ALIVE_TIME); + } + + SCHEDULED_EXECUTOR_SERVICE.setCorePoolSize(serviceCategory.getCorePoolSize()); + SCHEDULED_EXECUTOR_SERVICE.setMaximumPoolSize(serviceCategory.getMaximumPoolSize()); + SCHEDULED_EXECUTOR_SERVICE.setKeepAliveTime(serviceCategory.getKeepAliveTime(), TimeUnit.MILLISECONDS); } public static void schedule(AbstractService abstractService) { - schedule(abstractService, abstractService.getDelay(), abstractService.getInterval()).ifPresent(abstractService::setScheduledFuture); + try { + if (!abstractService.prepare()) { + throw new IllegalStateException("Service preparation failed"); + } + + schedule(abstractService, abstractService.getDelay(), abstractService.getInterval()).ifPresent(abstractService::setScheduledFuture); + } catch (Exception ex) { + DiscordMusic.getInstance().getLogger().error("Encountered an error while scheduling service", ex); + } + } + + public static Optional schedule(Runnable runnable) { + return schedule(runnable, 0L, 0L); } public static Optional schedule(Runnable runnable, long delay, long interval) { + return schedule(runnable, delay, interval, TimeUnit.MILLISECONDS); + } + + public static Optional schedule(Runnable runnable, long delay, long interval, TimeUnit unit) { try { if (interval <= 0L) { - return Optional.of(getScheduledExecutorService().schedule(runnable, Math.max(delay, 0L), TimeUnit.MILLISECONDS)); + return Optional.of(SCHEDULED_EXECUTOR_SERVICE.schedule(runnable, Math.max(delay, 0L), unit)); } - return Optional.of(getScheduledExecutorService().scheduleWithFixedDelay(runnable, Math.max(delay, 0L), Math.max(interval, 0L), TimeUnit.MILLISECONDS)); - } catch (RuntimeException ex) { - DiscordMusic.getInstance().getLogger().error("Encountered an error processing {}::schedule", "ServiceManager", ex); + return Optional.of(SCHEDULED_EXECUTOR_SERVICE.scheduleWithFixedDelay(runnable, Math.max(delay, 0L), Math.max(interval, 0L), unit)); + } catch (Exception ex) { + DiscordMusic.getInstance().getLogger().error("Encountered an error while scheduling service", ex); return Optional.empty(); } } - public static ScheduledExecutorService getScheduledExecutorService() { - return SCHEDULED_EXECUTOR_SERVICE; + public static void shutdown() { + try { + SCHEDULED_EXECUTOR_SERVICE.shutdown(); + if (!SCHEDULED_EXECUTOR_SERVICE.awaitTermination(5000L, TimeUnit.MILLISECONDS)) { + throw new InterruptedException(); + } + + DiscordMusic.getInstance().getLogger().info("Successfully terminated threads, continuing with shutdown process..."); + } catch (InterruptedException | RuntimeException ex) { + DiscordMusic.getInstance().getLogger().error("Failed to terminate threads, continuing with shutdown process..."); + } } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/service/AbstractService.java b/src/main/java/io/github/lxgaming/discordmusic/service/AbstractService.java index bd0a613..671a56c 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/service/AbstractService.java +++ b/src/main/java/io/github/lxgaming/discordmusic/service/AbstractService.java @@ -25,44 +25,46 @@ public abstract class AbstractService implements Runnable { private long delay; private long interval; - private transient ScheduledFuture scheduledFuture; + private ScheduledFuture scheduledFuture; public final void run() { try { execute(); } catch (Exception ex) { - DiscordMusic.getInstance().getLogger().error("Encountered an error processing {}::run", getClass().getSimpleName(), ex); + DiscordMusic.getInstance().getLogger().error("Encountered an error while executing {}", getClass().getSimpleName(), ex); getScheduledFuture().cancel(false); } } - public abstract void execute(); + public abstract boolean prepare(); + + public abstract void execute() throws Exception; public boolean isRunning() { return getScheduledFuture() != null && (!getScheduledFuture().isDone() || getScheduledFuture().getDelay(TimeUnit.MILLISECONDS) > 0L); } - public long getDelay() { + public final long getDelay() { return delay; } - protected void setDelay(long delay) { + protected final void setDelay(long delay) { this.delay = delay; } - public long getInterval() { + public final long getInterval() { return interval; } - protected void setInterval(long interval) { + protected final void setInterval(long interval) { this.interval = interval; } - public ScheduledFuture getScheduledFuture() { + public final ScheduledFuture getScheduledFuture() { return scheduledFuture; } - public void setScheduledFuture(ScheduledFuture scheduledFuture) { + public final void setScheduledFuture(ScheduledFuture scheduledFuture) { this.scheduledFuture = scheduledFuture; } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/service/MessageService.java b/src/main/java/io/github/lxgaming/discordmusic/service/MessageService.java index 40752d3..1e1884e 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/service/MessageService.java +++ b/src/main/java/io/github/lxgaming/discordmusic/service/MessageService.java @@ -17,6 +17,8 @@ package io.github.lxgaming.discordmusic.service; import io.github.lxgaming.discordmusic.DiscordMusic; +import io.github.lxgaming.discordmusic.configuration.Config; +import io.github.lxgaming.discordmusic.configuration.category.MessageCategory; import io.github.lxgaming.discordmusic.manager.MessageManager; import net.dv8tion.jda.api.entities.Message; @@ -25,42 +27,43 @@ public class MessageService extends AbstractService { - private long deleteInterval; - - public MessageService() { - setInterval(5000L); - setDeleteInterval(60000L); + @Override + public boolean prepare() { + setInterval(1000L); + return true; } @Override public void execute() { - synchronized (MessageManager.getMessages()) { - for (Iterator iterator = MessageManager.getMessages().iterator(); iterator.hasNext(); ) { + Instant deleteTime = DiscordMusic.getInstance().getConfig() + .map(Config::getMessageCategory) + .map(MessageCategory::getDeleteInternal) + .map(deleteInternal -> Instant.now().minusMillis(deleteInternal)) + .orElse(null); + if (deleteTime == null) { + DiscordMusic.getInstance().getLogger().warn("Failed to calculate delete time"); + return; + } + + synchronized (MessageManager.MESSAGES) { + for (Iterator iterator = MessageManager.MESSAGES.iterator(); iterator.hasNext(); ) { Message message = iterator.next(); - if (message == null || message.getTimeCreated() == null || message.getIdLong() == 0L) { + if (message.getIdLong() == 0L) { iterator.remove(); continue; } - if (message.getTimeCreated().toInstant().toEpochMilli() > Instant.now().minusMillis(getDeleteInterval()).toEpochMilli()) { + if (message.getTimeCreated().toInstant().isAfter(deleteTime)) { continue; } message.delete().queue( success -> DiscordMusic.getInstance().getLogger().debug("Successfully deleted Message {}", message.getIdLong()), - failure -> DiscordMusic.getInstance().getLogger().error("Encountered an error deleting Message {}", message.getIdLong(), failure) + failure -> DiscordMusic.getInstance().getLogger().error("Encountered an error deleting message {}", message.getIdLong(), failure) ); iterator.remove(); } } } - - private long getDeleteInterval() { - return deleteInterval; - } - - private void setDeleteInterval(long deleteInterval) { - this.deleteInterval = deleteInterval; - } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/util/DiscordData.java b/src/main/java/io/github/lxgaming/discordmusic/util/DiscordData.java deleted file mode 100644 index a735bee..0000000 --- a/src/main/java/io/github/lxgaming/discordmusic/util/DiscordData.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2018 Alex Thomson - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.github.lxgaming.discordmusic.util; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Message; - -public class DiscordData { - - private final Guild guild; - private final Message message; - - public DiscordData(Message message) { - this(message.getGuild(), message); - } - - public DiscordData(Guild guild, Message message) { - this.guild = guild; - this.message = message; - } - - public boolean isValid() { - return getGuild() != null && getMessage() != null; - } - - public Guild getGuild() { - return guild; - } - - public Message getMessage() { - return message; - } - - @Override - public String toString() { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("channel", getMessage().getChannel().getIdLong()); - jsonObject.addProperty("guild", getGuild().getIdLong()); - jsonObject.addProperty("message", getMessage().getIdLong()); - jsonObject.addProperty("user", getMessage().getAuthor().getIdLong()); - return new Gson().toJson(jsonObject); - } -} \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/util/Reference.java b/src/main/java/io/github/lxgaming/discordmusic/util/Reference.java index 2afc5d0..b10898d 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/util/Reference.java +++ b/src/main/java/io/github/lxgaming/discordmusic/util/Reference.java @@ -18,9 +18,9 @@ public class Reference { - public static final String APP_ID = "discordmusic"; - public static final String APP_NAME = "DiscordMusic"; - public static final String APP_VERSION = "2.1.6"; + public static final String ID = "discordmusic"; + public static final String NAME = "DiscordMusic"; + public static final String VERSION = "2.1.6"; public static final String AUTHORS = "LX_Gaming"; public static final String SOURCE = "https://github.com/LXGaming/DiscordMusic"; public static final String WEBSITE = "https://lxgaming.github.io/"; diff --git a/src/main/java/io/github/lxgaming/discordmusic/util/ShutdownHook.java b/src/main/java/io/github/lxgaming/discordmusic/util/ShutdownHook.java index ebd624d..b4c4a6b 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/util/ShutdownHook.java +++ b/src/main/java/io/github/lxgaming/discordmusic/util/ShutdownHook.java @@ -19,37 +19,16 @@ import io.github.lxgaming.discordmusic.DiscordMusic; import io.github.lxgaming.discordmusic.manager.AccountManager; import io.github.lxgaming.discordmusic.manager.ServiceManager; -import net.dv8tion.jda.api.JDA; import org.apache.logging.log4j.LogManager; -import java.util.concurrent.TimeUnit; - public class ShutdownHook extends Thread { @Override public void run() { Thread.currentThread().setName("Shutdown Thread"); DiscordMusic.getInstance().getLogger().info("Shutting down..."); - shutdownExecutorService(); - shutdownJDA(); + AccountManager.shutdown(); + ServiceManager.shutdown(); LogManager.shutdown(); } - - private void shutdownExecutorService() { - try { - ServiceManager.getScheduledExecutorService().shutdown(); - if (!ServiceManager.getScheduledExecutorService().awaitTermination(2000, TimeUnit.MILLISECONDS)) { - throw new InterruptedException(); - } - - DiscordMusic.getInstance().getLogger().info("Successfully terminated threads, continuing with shutdown process..."); - } catch (InterruptedException | RuntimeException ex) { - DiscordMusic.getInstance().getLogger().error("Failed to terminate threads, continuing with shutdown process..."); - } - } - - private void shutdownJDA() { - AccountManager.getJDA().ifPresent(JDA::shutdown); - DiscordMusic.getInstance().getLogger().info("JDA Shutdown"); - } } \ No newline at end of file diff --git a/src/main/java/io/github/lxgaming/discordmusic/util/Toolbox.java b/src/main/java/io/github/lxgaming/discordmusic/util/Toolbox.java index 8206e21..e8b19a2 100644 --- a/src/main/java/io/github/lxgaming/discordmusic/util/Toolbox.java +++ b/src/main/java/io/github/lxgaming/discordmusic/util/Toolbox.java @@ -16,8 +16,6 @@ package io.github.lxgaming.discordmusic.util; -import net.dv8tion.jda.api.entities.ISnowflake; -import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.concurrent.BasicThreadFactory; @@ -29,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Optional; import java.util.concurrent.LinkedBlockingQueue; @@ -38,6 +37,16 @@ public class Toolbox { + /** + * Removes non-printable characters (excluding new line and carriage return) in the provided {@link java.lang.String String}. + * + * @param string The {@link java.lang.String String} to filter. + * @return The filtered {@link java.lang.String String}. + */ + public static String filter(String string) { + return string.replaceAll("[^\\x20-\\x7E\\x0A\\x0D]", ""); + } + /** * Decodes the provided {@link java.lang.String String} into a {@link java.awt.Color Color}. * @@ -52,19 +61,8 @@ public static Optional decodeColor(String string) { } } - /** - * Removes non-printable characters (excluding new line and carriage return) in the provided {@link java.lang.String String}. - * - * @param string The {@link java.lang.String String} to filter. - * @return The filtered {@link java.lang.String String}. - */ - public static String filter(String string) { - return RegExUtils.replaceAll(string, "[^\\x20-\\x7E\\x0A\\x0D]", ""); - } - - public static String getTimeString(long time) { - time = Math.abs(time); - long second = time / 1000; + public static String getTimeString(long millisecond) { + long second = Math.abs(millisecond) / 1000; long minute = second / 60; long hour = minute / 60; long day = hour / 24; @@ -88,13 +86,16 @@ public static void appendUnit(StringBuilder stringBuilder, long unit, String sin stringBuilder.append(", "); } - stringBuilder.append(unit).append(" "); - if (unit == 1) { - stringBuilder.append(singular); - } else { - stringBuilder.append(plural); - } + stringBuilder.append(unit).append(" ").append(formatUnit(unit, singular, plural)); + } + } + + public static String formatUnit(long unit, String singular, String plural) { + if (unit == 1) { + return singular; } + + return plural; } public static Optional parseInteger(String string) { @@ -122,12 +123,12 @@ public static Optional parseUrl(String url) { } public static boolean containsIgnoreCase(Collection list, String targetString) { - if (list == null || list.isEmpty()) { + if (list == null || targetString == null) { return false; } for (String string : list) { - if (StringUtils.equalsIgnoreCase(string, targetString)) { + if (string != null && string.equalsIgnoreCase(targetString)) { return true; } } @@ -143,25 +144,17 @@ public static Optional newInstance(Class typeOfT) { } } - public static ThreadFactory buildThreadFactory(String namingPattern) { - return new BasicThreadFactory.Builder().namingPattern(namingPattern).daemon(true).priority(Thread.NORM_PRIORITY).build(); - } - - public static Optional getIdLong(ISnowflake snowflake) { - if (snowflake != null) { - return Optional.of(snowflake.getIdLong()); - } - - return Optional.empty(); - } - - public static Optional getPath() { + public static Path getPath() { String userDir = System.getProperty("user.dir"); if (StringUtils.isNotBlank(userDir)) { - return Optional.of(Paths.get(userDir)); + return Paths.get(userDir); } - return Optional.empty(); + return Paths.get("."); + } + + public static ThreadFactory newThreadFactory(String namingPattern) { + return new BasicThreadFactory.Builder().namingPattern(namingPattern).daemon(true).priority(Thread.NORM_PRIORITY).build(); } @SafeVarargs @@ -169,6 +162,15 @@ public static ArrayList newArrayList(E... elements) { return Stream.of(elements).collect(Collectors.toCollection(ArrayList::new)); } + public static HashMap newHashMap() { + return new HashMap<>(); + } + + @SafeVarargs + public static HashSet newHashSet(E... elements) { + return Stream.of(elements).collect(Collectors.toCollection(HashSet::new)); + } + @SafeVarargs public static LinkedBlockingQueue newLinkedBlockingQueue(E... elements) { return Stream.of(elements).collect(Collectors.toCollection(LinkedBlockingQueue::new)); @@ -178,8 +180,4 @@ public static LinkedBlockingQueue newLinkedBlockingQueue(E... elements) { public static LinkedHashSet newLinkedHashSet(E... elements) { return Stream.of(elements).collect(Collectors.toCollection(LinkedHashSet::new)); } - - public static HashMap newHashMap() { - return new HashMap<>(); - } } \ No newline at end of file