diff --git a/bot.config.example b/bot.config.example index 5495ed4..f6fe2c0 100644 --- a/bot.config.example +++ b/bot.config.example @@ -1,8 +1,8 @@ BOT_TOKEN= BOT_PREFIX= BOT_OWNER= -BOT_OWNERGUILD= -BOT_ERRORCHANNEL= +BOT_PAPISID= +BOT_PSID= MYSQL_HOST= MYSQL_USER= diff --git a/pom.xml b/pom.xml index 06f5297..0742d6d 100644 --- a/pom.xml +++ b/pom.xml @@ -91,6 +91,11 @@ https://m2.dv8tion.net/releases + + jitpack + https://jitpack.io + + @@ -99,6 +104,16 @@ JDA 4.4.0_350 + + + + + + + com.github.walkyst + lavaplayer-fork + 1.3.97 + com.squareup.okhttp3 @@ -145,11 +160,6 @@ commons-lang3 3.12.0 - - com.sedmelluq - lavaplayer - 1.3.78 - junit junit diff --git a/sql/add_debug_field_to_guilds_table.sql b/sql/add_debug_field_to_guilds_table.sql new file mode 100644 index 0000000..accb099 --- /dev/null +++ b/sql/add_debug_field_to_guilds_table.sql @@ -0,0 +1 @@ +ALTER TABLE `guilds` ADD `debug` BOOLEAN NOT NULL DEFAULT '1' AFTER `logging`; \ No newline at end of file diff --git a/src/main/java/netneutrality/GuildManager.java b/src/main/java/netneutrality/GuildManager.java index e657422..8d1b5a0 100644 --- a/src/main/java/netneutrality/GuildManager.java +++ b/src/main/java/netneutrality/GuildManager.java @@ -10,6 +10,8 @@ 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.TextChannel; +import netneutrality.db.DBController; +import netneutrality.db.controllers.DBGuild; import netneutrality.db.entities.OGuild; import netneutrality.handler.ratelimiter.IMessageRateLimiter; import netneutrality.handler.ratelimiter.MessageRateLimiterImpl; @@ -23,7 +25,9 @@ import java.util.concurrent.ConcurrentHashMap; public class GuildManager { public enum GuildSetting { - MUSIC_ROLE("music.role", null), MUSIC_CHANNEL("music.channel", null), BLACKLIST_CHANNELS("blacklist.exclude.channels", null); + MUSIC_ROLE("music.role", null), + MUSIC_CHANNEL("music.channel", null), + BLACKLIST_CHANNELS("blacklist.exclude.channels", null); private final String setting; private final String defaultValue; @@ -58,6 +62,8 @@ public class GuildManager { private GuildManager(Guild guild) { this.guild = guild; + handleJoinEvent(); + this.guildEntity = new OGuild(guild.getId()); this.rateLimiter = new MessageRateLimiterImpl(); @@ -72,14 +78,40 @@ public class GuildManager { } } + // Getter + public static Map getManagers() { + return managers; + } + public static GuildManager getManager(String guildId) { return managers.getOrDefault(guildId, null); } - public static Map getManagers() { - return managers; + public String getSetting(GuildSetting key) { + return guildEntity.getSettings().getSettingByKey(key.toString()); } + public boolean isLoggingEnabled() { + return guildEntity.isLogging(); + } + + public boolean isDebugEnabled() { + return guildEntity.isDebug(); + } + + public Map getSettings() { + return guildEntity.getSettings().getSettings(); + } + + public IMessageRateLimiter getRateLimiter() { + return rateLimiter; + } + + public Guild getGuild() { + return guild; + } + + public static boolean reloadSettingsForGuild(String guildId) { if (managers.containsKey(guildId)) { GuildManager manager = managers.get(guildId); @@ -111,33 +143,28 @@ public class GuildManager { MessageFunction.checkBlacklist(guild, message, channel); } - public String getSetting(String key) { - return guildEntity.getSettings().getSettingByKey(key); - } - - public String getSetting(GuildSetting key) { - return guildEntity.getSettings().getSettingByKey(key.toString()); - } - - public Map getSettings() { - return guildEntity.getSettings().getSettings(); + public boolean existInDb() { + return DBController.get().exists("guilds", "guild_id", guild.getId()); } public void reloadSettings() { guildEntity.reloadSettings(); } - public IMessageRateLimiter getRateLimiter() { - return rateLimiter; - } + public void handleJoinEvent() { + if (!existInDb()) { + ((DBGuild) DBController.get("guild")).insertGuildInDB(guild); - public Guild getGuild() { - return guild; - } - - - - private void load() { + guild.getTextChannels() + .stream() + .filter(textChannel -> textChannel.getName().equals("debug") || textChannel.getName().equals("log")) + .forEach(textChannel -> textChannel.sendMessage("Error logging enabled on channel " + textChannel.getAsMention()).queue()); + } } + + public void removeFromDB() { + ((DBGuild) DBController.get("guild")).removeGuildInDB(guild); + } + } diff --git a/src/main/java/netneutrality/MusicBot.java b/src/main/java/netneutrality/MusicBot.java index 6ee210f..e16870c 100644 --- a/src/main/java/netneutrality/MusicBot.java +++ b/src/main/java/netneutrality/MusicBot.java @@ -3,13 +3,14 @@ package netneutrality; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.requests.GatewayIntent; import netneutrality.command.CommandManager; import netneutrality.db.DBController; -import netneutrality.handler.message.EditHandler; -import netneutrality.handler.message.MessageReceivedHandler; -import netneutrality.handler.ServerJoinHandler; +import netneutrality.handler.hooks.message.EditHandler; +import netneutrality.handler.hooks.message.MessageReceivedHandler; +import netneutrality.handler.hooks.guilds.ServerJoinHandler; import netneutrality.http.server.WebApi; import netneutrality.music.MusicManager; import netneutrality.thread.BaseThreadFactory; @@ -29,10 +30,11 @@ public class MusicBot { public static void main(String[] args) { DBController.init(); + initJDA(); CommandManager.init(); - MusicManager.registerSources(); + MusicManager.initPlayerManager(); jda.getPresence().setActivity(Activity.watching("me load...")); jda.addEventListener(new MessageReceivedHandler(), new EditHandler(), new ServerJoinHandler()); @@ -66,6 +68,11 @@ public class MusicBot { return jda; } + public static User getSelf() { + return jda.getSelfUser(); + + } + private static void disconnect() { if (jda != null) { jda.shutdown(); diff --git a/src/main/java/netneutrality/ThreadManager.java b/src/main/java/netneutrality/ThreadManager.java index 03fbb15..2530aae 100644 --- a/src/main/java/netneutrality/ThreadManager.java +++ b/src/main/java/netneutrality/ThreadManager.java @@ -25,27 +25,14 @@ public class ThreadManager { ExecutorService executor; switch (type) { - case FIXED: - executor = executors.computeIfAbsent(name, s -> Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new BaseThreadFactory(name))); - break; - case SCHEDULED: - executor = executors.computeIfAbsent(name, s -> Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new BaseThreadFactory(name))); - break; - default: - executor = executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThreadFactory(name))); + case FIXED -> executor = executors.computeIfAbsent(name, s -> Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new BaseThreadFactory(name))); + case SCHEDULED -> executor = executors.computeIfAbsent(name, s -> Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new BaseThreadFactory(name))); + default -> executor = executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThreadFactory(name))); } return executor; } - public static Future dispatch(ExecutorService executor, Runnable task) { - return executor.submit(task); - } - - public static Future dispatch(ExecutorService executor, Callable task) { - return executor.submit(task); - } - public static void shutdownExecutor() { System.out.println("[Executor] Shutting down..."); diff --git a/src/main/java/netneutrality/command/AbstractCommand.java b/src/main/java/netneutrality/command/AbstractCommand.java index 0b13e68..2bceb6d 100644 --- a/src/main/java/netneutrality/command/AbstractCommand.java +++ b/src/main/java/netneutrality/command/AbstractCommand.java @@ -20,7 +20,7 @@ public abstract class AbstractCommand implements ICommand { * * @return the name of the command. */ - public abstract String getCommand(); + public abstract String getCommandName(); /** * @return all the aliases the command has diff --git a/src/main/java/netneutrality/command/CommandContext.java b/src/main/java/netneutrality/command/CommandContext.java index 0655d4e..1695a55 100644 --- a/src/main/java/netneutrality/command/CommandContext.java +++ b/src/main/java/netneutrality/command/CommandContext.java @@ -10,6 +10,8 @@ import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import netneutrality.ThreadManager; +import netneutrality.exceptions.CommandErrorException; +import netneutrality.exceptions.CommandExecutionException; import netneutrality.handler.LogHandler; import netneutrality.utils.Settings; import netneutrality.utils.UserFunction; @@ -51,7 +53,7 @@ public class CommandContext { } public String getArg(int index) { - return getArgumentsAsArray()[index]; + return getArgumentsAsArray()[index]; } public String[] getArgumentsAsArray() { @@ -108,6 +110,10 @@ public class CommandContext { } } + public void reply(String format, Object... arguments) { + reply(String.format(format, arguments)); + } + public void reply(Message msg) { if (channel != null) { channel.sendMessage(msg).queue(); @@ -142,20 +148,20 @@ public class CommandContext { this.command = command; //TODO: Add usage check - if (command.needAdmin()) { - if (!UserFunction.isAdmin(member)) { - return; + try { + if (command.needAdmin()) { + if (!UserFunction.isAdmin(member)) { + return; + } } - } - if (command.canBeExecutedBy(guild, member)) { - - try { + if (command.canBeExecutedBy(guild, member)) { command.execute(this); - } catch (Exception e) { - LogHandler.log(e); } - + } catch (CommandErrorException | CommandExecutionException e) { + LogHandler.log(e); + } catch (Exception e) { + LogHandler.log(new CommandExecutionException("Error during command execution", this, e)); } } } diff --git a/src/main/java/netneutrality/command/CommandManager.java b/src/main/java/netneutrality/command/CommandManager.java index bf683bd..faf4ddc 100644 --- a/src/main/java/netneutrality/command/CommandManager.java +++ b/src/main/java/netneutrality/command/CommandManager.java @@ -44,8 +44,8 @@ public class CommandManager { if (!command.isEnabled()) continue; - if (!commands.containsKey(command.getCommand())) { - commands.put(command.getCommand(), command); + if (!commands.containsKey(command.getCommandName())) { + commands.put(command.getCommandName(), command); } } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { diff --git a/src/main/java/netneutrality/command/basic/HelpCommand.java b/src/main/java/netneutrality/command/basic/HelpCommand.java index d5e0395..4b94212 100644 --- a/src/main/java/netneutrality/command/basic/HelpCommand.java +++ b/src/main/java/netneutrality/command/basic/HelpCommand.java @@ -30,7 +30,7 @@ public class HelpCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "help"; } diff --git a/src/main/java/netneutrality/command/basic/PingCommand.java b/src/main/java/netneutrality/command/basic/PingCommand.java index de9a442..be1ecd8 100644 --- a/src/main/java/netneutrality/command/basic/PingCommand.java +++ b/src/main/java/netneutrality/command/basic/PingCommand.java @@ -24,7 +24,7 @@ public class PingCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "ping"; } diff --git a/src/main/java/netneutrality/command/bot/ConfigureCommand.java b/src/main/java/netneutrality/command/bot/ConfigureCommand.java index 56051b3..7616b68 100644 --- a/src/main/java/netneutrality/command/bot/ConfigureCommand.java +++ b/src/main/java/netneutrality/command/bot/ConfigureCommand.java @@ -22,7 +22,7 @@ public class ConfigureCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "configure"; } diff --git a/src/main/java/netneutrality/command/crypto/BitcoinPriceCommand.java b/src/main/java/netneutrality/command/crypto/BitcoinPriceCommand.java index 68a9414..7eb25cd 100644 --- a/src/main/java/netneutrality/command/crypto/BitcoinPriceCommand.java +++ b/src/main/java/netneutrality/command/crypto/BitcoinPriceCommand.java @@ -34,7 +34,7 @@ public class BitcoinPriceCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "bitcoin"; } diff --git a/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java b/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java index 3855472..84ca8af 100644 --- a/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java +++ b/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java @@ -33,7 +33,7 @@ public class CryptoPriceCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "crypto"; } diff --git a/src/main/java/netneutrality/command/crypto/EthereumPriceCommand.java b/src/main/java/netneutrality/command/crypto/EthereumPriceCommand.java index 2a17447..dacf593 100644 --- a/src/main/java/netneutrality/command/crypto/EthereumPriceCommand.java +++ b/src/main/java/netneutrality/command/crypto/EthereumPriceCommand.java @@ -34,7 +34,7 @@ public class EthereumPriceCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "ethereum"; } diff --git a/src/main/java/netneutrality/command/crypto/LitecoinPriceCommand.java b/src/main/java/netneutrality/command/crypto/LitecoinPriceCommand.java index eb8e3b7..2d5e70b 100644 --- a/src/main/java/netneutrality/command/crypto/LitecoinPriceCommand.java +++ b/src/main/java/netneutrality/command/crypto/LitecoinPriceCommand.java @@ -34,7 +34,7 @@ public class LitecoinPriceCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "litecoin"; } diff --git a/src/main/java/netneutrality/command/message/BlacklistCommand.java b/src/main/java/netneutrality/command/message/BlacklistCommand.java index b160d53..040556a 100644 --- a/src/main/java/netneutrality/command/message/BlacklistCommand.java +++ b/src/main/java/netneutrality/command/message/BlacklistCommand.java @@ -12,6 +12,7 @@ import netneutrality.command.CommandType; import netneutrality.db.DBController; import netneutrality.db.controllers.DBBlacklist; import netneutrality.db.models.MBlacklist; +import netneutrality.exceptions.CommandExecutionException; public class BlacklistCommand extends AbstractCommand { @@ -26,7 +27,7 @@ public class BlacklistCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "blacklist"; } @@ -53,6 +54,11 @@ public class BlacklistCommand extends AbstractCommand { @Override public void execute(CommandContext context) { String[] args = context.getArgumentsAsArray(); + DBBlacklist controller = ((DBBlacklist) DBController.get("blacklist")); + + if (controller == null) { + throw new CommandExecutionException("Error getting database controller", context, null); + } if (args.length > 0 && args.length < 3) { String word = (args.length == 2 ? args[1] : ""); @@ -63,7 +69,7 @@ public class BlacklistCommand extends AbstractCommand { context.getChannel().sendMessage("Retrieving list, please wait...").queue(t -> { StringBuilder sb = new StringBuilder(); - ((DBBlacklist) DBController.get("blacklist")).getBlacklistFromServer(context.getGuild().getId(), mBlacklists -> { + controller.getBlacklistFromServer(context.getGuild().getId(), mBlacklists -> { for (MBlacklist bl : mBlacklists) { sb.append(bl.getWord()).append(" -> ").append(bl.isEnabled() ? "enabled" : "disabled").append("\n"); } @@ -77,48 +83,40 @@ public class BlacklistCommand extends AbstractCommand { case "add": - ((DBBlacklist) DBController.get("blacklist")).add(new MBlacklist(word, true, context.getDiscordUser().getId(), context.getGuild().getId()), response -> { - if (response) { - context.getChannel().sendMessage("Added the word \"" + word + "\" to the blacklist.").queue(); - } else { - context.getChannel().sendMessage("Error adding \"" + word + "\" to the blacklist. It's already blacklisted!").queue(); - } - }); + if (controller.add(new MBlacklist(word, true, context.getDiscordUser().getId(), context.getGuild().getId()))) { + context.reply(String.format("Added the word [%s] to the blacklist.", word)); + } else { + context.reply(String.format("Error adding [%s] to the blacklist. It's already blacklisted!", word)); + } break; case "remove": - ((DBBlacklist) DBController.get("blacklist")).delete(word, context.getGuild().getId(), success -> { - if (success) { - context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); - } else { - context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); - } - }); + if (controller.delete(word, context.getGuild().getId())) { + context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); + } else { + context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); + } break; case "disable": - ((DBBlacklist) DBController.get("blacklist")).disable(word, context.getGuild().getId(), success -> { - if (success) { - context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); - } else { - context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); - } - }); + if (controller.disable(word, context.getGuild().getId())) { + context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); + } else { + context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); + } break; case "enable": - ((DBBlacklist) DBController.get("blacklist")).enable(word, context.getGuild().getId(), success -> { - if (success) { - context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); - } else { - context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); - } - }); + if (controller.enable(word, context.getGuild().getId())) { + context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); + } else { + context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); + } break; diff --git a/src/main/java/netneutrality/command/message/PruneCommand.java b/src/main/java/netneutrality/command/message/PruneCommand.java index 94ae9cd..dda3d85 100644 --- a/src/main/java/netneutrality/command/message/PruneCommand.java +++ b/src/main/java/netneutrality/command/message/PruneCommand.java @@ -24,7 +24,7 @@ public class PruneCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "prune"; } diff --git a/src/main/java/netneutrality/command/music/BitconnectCommand.java b/src/main/java/netneutrality/command/music/BitconnectCommand.java index 713ff74..6701413 100644 --- a/src/main/java/netneutrality/command/music/BitconnectCommand.java +++ b/src/main/java/netneutrality/command/music/BitconnectCommand.java @@ -20,7 +20,7 @@ public class BitconnectCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "bitconnect"; } diff --git a/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java b/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java index 995b7f2..0af4460 100644 --- a/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java +++ b/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java @@ -22,7 +22,7 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "playing"; } diff --git a/src/main/java/netneutrality/command/music/DeleteQueueCommand.java b/src/main/java/netneutrality/command/music/DeleteQueueCommand.java index 44fc51f..b340dad 100644 --- a/src/main/java/netneutrality/command/music/DeleteQueueCommand.java +++ b/src/main/java/netneutrality/command/music/DeleteQueueCommand.java @@ -24,7 +24,7 @@ public class DeleteQueueCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "deletequeue"; } diff --git a/src/main/java/netneutrality/command/music/JoinCommand.java b/src/main/java/netneutrality/command/music/JoinCommand.java index 1242f7e..39f8832 100644 --- a/src/main/java/netneutrality/command/music/JoinCommand.java +++ b/src/main/java/netneutrality/command/music/JoinCommand.java @@ -10,6 +10,8 @@ package netneutrality.command.music; import net.dv8tion.jda.api.entities.VoiceChannel; import netneutrality.command.AbstractMusicCommand; import netneutrality.command.CommandContext; +import netneutrality.exceptions.CommandErrorException; +import netneutrality.exceptions.CommandExecutionException; import netneutrality.music.MusicManager; import netneutrality.utils.MusicUtils; @@ -21,7 +23,7 @@ public class JoinCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "join"; } @@ -43,7 +45,18 @@ public class JoinCommand extends AbstractMusicCommand { @Override public void execute(CommandContext context) { MusicManager player = MusicManager.get(context.getGuild()); - MusicUtils.checkIfConnected(player, context); + + if (context.getGuildUser().getVoiceState() == null) { + throw new CommandExecutionException("Voice state is null", context, null); + } + + if (!context.getGuildUser().getVoiceState().inVoiceChannel()) { + throw new CommandErrorException("You are not in a voice channel", context, null); + } + + if (player.isConnected()) { + throw new CommandErrorException("Player is already in a voice channel", context, null); + } VoiceChannel vChannel = context.getGuildUser().getVoiceState().getChannel(); player.connect(vChannel); diff --git a/src/main/java/netneutrality/command/music/LeaveCommand.java b/src/main/java/netneutrality/command/music/LeaveCommand.java index 71b578b..65a149b 100644 --- a/src/main/java/netneutrality/command/music/LeaveCommand.java +++ b/src/main/java/netneutrality/command/music/LeaveCommand.java @@ -24,7 +24,7 @@ public class LeaveCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "leave"; } diff --git a/src/main/java/netneutrality/command/music/PlayCommand.java b/src/main/java/netneutrality/command/music/PlayCommand.java index 52c4b81..6f6948e 100644 --- a/src/main/java/netneutrality/command/music/PlayCommand.java +++ b/src/main/java/netneutrality/command/music/PlayCommand.java @@ -19,7 +19,7 @@ public class PlayCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "play"; } diff --git a/src/main/java/netneutrality/command/music/SkipCommand.java b/src/main/java/netneutrality/command/music/SkipCommand.java index 257d58b..a32964b 100644 --- a/src/main/java/netneutrality/command/music/SkipCommand.java +++ b/src/main/java/netneutrality/command/music/SkipCommand.java @@ -24,7 +24,7 @@ public class SkipCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "skip"; } diff --git a/src/main/java/netneutrality/command/music/StopCommand.java b/src/main/java/netneutrality/command/music/StopCommand.java index b8cc556..53747e3 100644 --- a/src/main/java/netneutrality/command/music/StopCommand.java +++ b/src/main/java/netneutrality/command/music/StopCommand.java @@ -21,7 +21,7 @@ public class StopCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "stop"; } diff --git a/src/main/java/netneutrality/command/music/ViewQueueCommand.java b/src/main/java/netneutrality/command/music/ViewQueueCommand.java index 0eaa4fb..9c51f90 100644 --- a/src/main/java/netneutrality/command/music/ViewQueueCommand.java +++ b/src/main/java/netneutrality/command/music/ViewQueueCommand.java @@ -26,7 +26,7 @@ public class ViewQueueCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "viewqueue"; } diff --git a/src/main/java/netneutrality/command/music/VolumeCommand.java b/src/main/java/netneutrality/command/music/VolumeCommand.java index 35a7fe2..4c2cf75 100644 --- a/src/main/java/netneutrality/command/music/VolumeCommand.java +++ b/src/main/java/netneutrality/command/music/VolumeCommand.java @@ -26,7 +26,7 @@ public class VolumeCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "volume"; } diff --git a/src/main/java/netneutrality/command/music/VoteSkipCommand.java b/src/main/java/netneutrality/command/music/VoteSkipCommand.java index d8ace4e..8e33acd 100644 --- a/src/main/java/netneutrality/command/music/VoteSkipCommand.java +++ b/src/main/java/netneutrality/command/music/VoteSkipCommand.java @@ -19,7 +19,7 @@ public class VoteSkipCommand extends AbstractMusicCommand { } @Override - public String getCommand() { + public String getCommandName() { return "voteskip"; } diff --git a/src/main/java/netneutrality/command/specific/DatabaseCommand.java b/src/main/java/netneutrality/command/specific/DatabaseCommand.java index e5bd4b0..e5ac876 100644 --- a/src/main/java/netneutrality/command/specific/DatabaseCommand.java +++ b/src/main/java/netneutrality/command/specific/DatabaseCommand.java @@ -34,7 +34,7 @@ public class DatabaseCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "database"; } diff --git a/src/main/java/netneutrality/command/specific/EvalMethod.java b/src/main/java/netneutrality/command/specific/EvalMethod.java index 21bbeaf..d9ba04a 100644 --- a/src/main/java/netneutrality/command/specific/EvalMethod.java +++ b/src/main/java/netneutrality/command/specific/EvalMethod.java @@ -31,7 +31,7 @@ public class EvalMethod extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "evaluate"; } diff --git a/src/main/java/netneutrality/command/specific/LoggingCommand.java b/src/main/java/netneutrality/command/specific/LoggingCommand.java index 22f275e..8e53884 100644 --- a/src/main/java/netneutrality/command/specific/LoggingCommand.java +++ b/src/main/java/netneutrality/command/specific/LoggingCommand.java @@ -23,7 +23,7 @@ public class LoggingCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "logging"; } diff --git a/src/main/java/netneutrality/command/specific/SellyCommand.java b/src/main/java/netneutrality/command/specific/SellyCommand.java index d629432..b538018 100644 --- a/src/main/java/netneutrality/command/specific/SellyCommand.java +++ b/src/main/java/netneutrality/command/specific/SellyCommand.java @@ -30,7 +30,7 @@ public class SellyCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "selly"; } diff --git a/src/main/java/netneutrality/command/specific/TestCommand.java b/src/main/java/netneutrality/command/specific/TestCommand.java index 9d7ef72..2407c6e 100644 --- a/src/main/java/netneutrality/command/specific/TestCommand.java +++ b/src/main/java/netneutrality/command/specific/TestCommand.java @@ -24,7 +24,7 @@ public class TestCommand extends AbstractCommand { } @Override - public String getCommand() { + public String getCommandName() { return "test"; } diff --git a/src/main/java/netneutrality/db/AsyncMySqlAction.java b/src/main/java/netneutrality/db/AsyncMySqlAction.java index 6370575..eea1256 100644 --- a/src/main/java/netneutrality/db/AsyncMySqlAction.java +++ b/src/main/java/netneutrality/db/AsyncMySqlAction.java @@ -37,70 +37,34 @@ public class AsyncMySqlAction { } public void async(Consumer success) { + switch (type) { - case INSERT: - ThreadManager.dispatch(executor, () -> { - db.insert(this.sqlString, this.params); - }); - break; - case UPDATE: - ThreadManager.dispatch(executor, () -> { - db.update(this.sqlString, this.params); - }); - break; + case INSERT -> executor.submit(() -> success.accept(new MTableModel(db.insert(this.sqlString, this.params)))); + case UPDATE -> executor.submit(() -> success.accept(new MTableModel(db.update(this.sqlString, this.params)))); + case DELETE -> executor.submit(() -> success.accept(new MTableModel(db.delete(this.sqlString, this.params)))); + case SELECT -> executor.submit(() -> { + ResultSet result = db.prepareAndExecute(this.sqlString, this.params); - case DELETE: - ThreadManager.dispatch(executor, () -> { - db.delete(this.sqlString, this.params); - }); - break; - - case SELECT: - ThreadManager.dispatch(executor, () -> { - ResultSet result = db.prepareAndExecute(this.sqlString, this.params); - MTableModel table = MysqlDatabase.convertToTableModel(result, tableName); - - success.accept(table); - }); - break; + success.accept(MysqlDatabase.convertToTableModel(result, tableName)); + }); } } public MTableModel blocking() { + MTableModel table = new MTableModel(); + try { - switch (type) { - case INSERT: - ThreadManager.dispatch(executor, () -> { - db.insert(this.sqlString, this.params); - }).get(); - - case UPDATE: - ThreadManager.dispatch(executor, () -> { - db.update(this.sqlString, this.params); - }).get(); - - case DELETE: - ThreadManager.dispatch(executor, () -> { - db.delete(this.sqlString, this.params); - }).get(); - - case SELECT: - Callable task = () -> { - ResultSet result = db.prepareAndExecute(this.sqlString, this.params); - MTableModel table = MysqlDatabase.convertToTableModel(result, tableName); - - return table; - }; - - Future future = ThreadManager.dispatch(executor, task); - return future.get(); - } + table = switch (type) { + case INSERT -> executor.submit(() -> new MTableModel(db.insert(this.sqlString, this.params))).get(); + case UPDATE -> executor.submit(() -> new MTableModel(db.update(this.sqlString, this.params))).get(); + case DELETE -> executor.submit(() -> new MTableModel(db.delete(this.sqlString, this.params))).get(); + case SELECT -> executor.submit(() -> db.prepareAndExecute(this.sqlString, this.tableName, this.params)).get(); + }; } catch (InterruptedException | ExecutionException e) { - return null; + return table; } - return null; + return table; } - } diff --git a/src/main/java/netneutrality/db/MysqlDatabase.java b/src/main/java/netneutrality/db/MysqlDatabase.java index 43592de..55afafa 100644 --- a/src/main/java/netneutrality/db/MysqlDatabase.java +++ b/src/main/java/netneutrality/db/MysqlDatabase.java @@ -10,11 +10,10 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; -import netneutrality.MusicBot; -import netneutrality.db.entities.EntityInterface; import netneutrality.db.models.MRowModel; import netneutrality.db.models.MTableModel; import netneutrality.exceptions.UnimplementedParameterException; +import netneutrality.handler.LogHandler; import netneutrality.utils.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,6 +21,7 @@ import org.slf4j.LoggerFactory; public class MysqlDatabase { private final static Logger logger = LoggerFactory.getLogger(MysqlDatabase.class); + private final static Object dmlLock = new Object(); protected Connection connection; private final String dbName; @@ -37,8 +37,11 @@ public class MysqlDatabase { public static CommandType stringToType(String str) { return CommandType.valueOf(str); } - } + public String getType() { + return type; + } + } protected MysqlDatabase(String dbName) { this.dbName = dbName; @@ -51,7 +54,7 @@ public class MysqlDatabase { connection = new MysqlConnector(dbName, dbUser, dbHost, dbPass).connect().getConnection(); } catch (SQLException e) { logger.error("Error connecting to database. Shutting down..", e); - System.exit(0); + System.exit(-1); } } @@ -68,7 +71,7 @@ public class MysqlDatabase { stmt = connection.createStatement(); return stmt.executeQuery(query); } catch (SQLException e) { - logger.error(e.toString()); + LogHandler.log(e); } return null; @@ -80,9 +83,8 @@ public class MysqlDatabase { * * @param sql The SQL query to execute * @param params The parameters to include in the query - * @return an integer of how many row were affected */ - protected synchronized int update(String sql, Object... params) { + protected int update(String sql, Object... params) { return executeUpdate(sql, params); } @@ -94,7 +96,7 @@ public class MysqlDatabase { * @param params The parameters to include in the query * @return an integer of how many row were affected */ - protected synchronized int insert(String sql, Object... params) { + protected int insert(String sql, Object... params) { return executeUpdate(sql, params); } @@ -106,27 +108,29 @@ public class MysqlDatabase { * @param params The parameters to include in the query * @return an integer of how many row were affected */ - protected synchronized int delete(String sql, Object... params) { + protected int delete(String sql, Object... params) { return executeUpdate(sql, params); } - public boolean exists(String table, String key, String value) { - return prepareAndExecuteAsync("SELECT 1 FROM " + table + " WHERE " + key + " = ?", value).blocking().isEmpty(); + private int executeUpdate(String sql, Object[] params) { + logger.debug("Query: " + sql); + + synchronized (dmlLock) { + try { + PreparedStatement query = connection.prepareStatement(sql); + resolveParameters(query, params); + return query.executeUpdate(); + } catch (SQLException e) { + LogHandler.log(e); + } + + return -1; + } } - private synchronized int executeUpdate(String sql, Object[] params) { - logger.debug("Query: " + sql); - - try { - PreparedStatement query = connection.prepareStatement(sql); - resolveParameters(query, params); - return query.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - } - - return -1; + public boolean exists(String table, String key, String value) { + return !prepareAndExecuteAsync(String.format("SELECT 1 FROM %s WHERE %s = ?", table, key), value).blocking().isEmpty(); } /** @@ -137,13 +141,12 @@ public class MysqlDatabase { * @param params The parameters to include in the query * @return a ResultSet object, which can be converted to a model using {@link MysqlDatabase#convertToTableModel(ResultSet, String)} */ - protected synchronized ResultSet prepareAndExecute(String sql, Object... params) { + protected ResultSet prepareAndExecute(String sql, Object... params) { try { PreparedStatement query = connection.prepareStatement(sql); resolveParameters(query, params); - ResultSet rs = query.executeQuery(); - return rs; + return query.executeQuery(); } catch (SQLException e) { logger.error(e.getMessage(), e); } @@ -151,6 +154,19 @@ public class MysqlDatabase { return null; } + protected MTableModel prepareAndExecute(String sql, String tableName, Object... params) { + + try { + PreparedStatement query = connection.prepareStatement(sql); + resolveParameters(query, params); + return convertToTableModel(query.executeQuery(), tableName); + } catch (SQLException e) { + logger.error(e.getMessage(), e); + } + + return null; + } + /** * Execute a SELECT statement with the specified parameters. * In the SQL query, where there is a parameter to be included, you need to replace it with ? @@ -206,8 +222,6 @@ public class MysqlDatabase { /** * Close the MySQL connection - * - * @throws SQLException */ public void close() throws SQLException { System.out.println("Closing database..."); @@ -249,8 +263,7 @@ public class MysqlDatabase { * @return a {@link MTableModel} with the appropriate column and rows */ protected static MTableModel convertToTableModel(ResultSet rs, String tableName) { - MTableModel table = new MTableModel(); - table.setName(tableName); + MTableModel table = new MTableModel(tableName); try { ResultSetMetaData metadata = rs.getMetaData(); diff --git a/src/main/java/netneutrality/db/controllers/DBBlacklist.java b/src/main/java/netneutrality/db/controllers/DBBlacklist.java index 04a2d0e..d6d0207 100644 --- a/src/main/java/netneutrality/db/controllers/DBBlacklist.java +++ b/src/main/java/netneutrality/db/controllers/DBBlacklist.java @@ -14,77 +14,36 @@ public class DBBlacklist extends AbstractController { private final Logger logger = LoggerFactory.getLogger(DBBlacklist.class); - public void add(MBlacklist obj, Consumer success) { - isAlreadyBlacklisted(obj.getWord(), obj.getServerId(), blacklisted -> { - if (blacklisted == 0) { - database.prepareAndExecuteAsync("INSERT INTO blacklist VALUES(?,?,?,?)", obj.getServerId(), obj.getWord(), obj.isEnabled(), obj.getCreatorId()).async(); - success.accept(true); - } else { - success.accept(false); - } - }); + public boolean add(MBlacklist obj) { + if (!isAlreadyBlacklisted(obj.getWord(), obj.getServerId())) { + return database.prepareAndExecuteAsync("INSERT INTO blacklist VALUES(?,?,?,?)", obj.getServerId(), obj.getWord(), obj.isEnabled(), obj.getCreatorId()).blocking().isSuccess(); + } + return false; } + public boolean delete(String word, String serverId) { + if (isAlreadyBlacklisted(word, serverId)) { + return database.prepareAndExecuteAsync("DELETE FROM blacklist WHERE word = ? AND guild_id = ?", word, serverId).blocking().isSuccess(); + } - - public void delete(String word, String serverId, Consumer success) { - isAlreadyBlacklisted(word, serverId, blacklisted -> { - if (blacklisted >= 1) { - database.prepareAndExecuteAsync("DELETE FROM blacklist WHERE word = ? AND guild_id = ?", word, serverId).async(); - logger.debug("removed word from blacklist"); - success.accept(true); - } else { - logger.info("not blacklisted"); - success.accept(false); - } - }); - + return false; } - public void enable(String word, String serverId, Consumer success) { - - isAlreadyBlacklisted(word, serverId, blacklisted -> { - if (blacklisted >= 1) { - database.prepareAndExecuteAsync("UPDATE blacklist SET enabled = 1 WHERE word = ? AND guild_id = ?", word, serverId).async(); - logger.info("enabled"); - success.accept(true); - } else { - logger.info("error enabling"); - success.accept(false); - } - }); + public boolean enable(String word, String serverId) { + if (isAlreadyBlacklisted(word, serverId)) { + return database.prepareAndExecuteAsync("UPDATE blacklist SET enabled = 1 WHERE word = ? AND guild_id = ?", word, serverId).blocking().isSuccess(); + } + return false; } - public void disable(String word, String serverId, Consumer success) { - - isAlreadyBlacklisted(word, serverId, blacklisted -> { - if (blacklisted >= 1) { - database.prepareAndExecuteAsync("UPDATE blacklist SET enabled = 0 WHERE word = ? AND guild_id = ?", word, serverId).async(); - logger.info("disabled"); - success.accept(true); - } else { - logger.info("error disabling"); - success.accept(false); - } - }); - - } - - @Deprecated - public void getBlacklistForWord(String word, String serverId, Consumer success) { - - database.prepareAndExecuteAsync("SELECT * FROM blacklist WHERE word = ? AND guild_id = ?", word, serverId).async((table -> { - MBlacklist blacklisted = null; - - if (table.getNbRows() > 0) { - blacklisted = new MBlacklist(table.getRow(0)); - } - success.accept(blacklisted); - - })); + public boolean disable(String word, String serverId) { + if (isAlreadyBlacklisted(word, serverId)) { + return database.prepareAndExecuteAsync("UPDATE blacklist SET enabled = 0 WHERE word = ? AND guild_id = ?", word, serverId).blocking().isSuccess(); + } + return false; } public void getBlacklistFromServer(String serverId, Consumer> success) { @@ -104,7 +63,6 @@ public class DBBlacklist extends AbstractController { } - @Deprecated public ArrayList getBlacklistFromServer(String serverId) { MTableModel model = database.prepareAndExecuteAsync("SELECT * FROM blacklist WHERE guild_id = ? AND enabled = 1", serverId).blocking(); @@ -130,17 +88,6 @@ public class DBBlacklist extends AbstractController { return false; } - private void isAlreadyBlacklisted(String word, String serverId, Consumer result) { - - database.prepareAndExecuteAsync("SELECT COUNT(*) FROM blacklist WHERE word = ? AND guild_id = ?", word, serverId).async(table -> { - if (!table.isEmpty()) { - int count = Integer.parseInt(table.getRowModel(0).getItem(0).toString()); - - result.accept(count); - } - }); - } - @Override public String getControllerName() { return "blacklist"; diff --git a/src/main/java/netneutrality/db/entities/AbstractEntity.java b/src/main/java/netneutrality/db/entities/AbstractEntity.java index 0831784..05767d3 100644 --- a/src/main/java/netneutrality/db/entities/AbstractEntity.java +++ b/src/main/java/netneutrality/db/entities/AbstractEntity.java @@ -8,6 +8,7 @@ package netneutrality.db.entities;/* import netneutrality.MusicBot; import netneutrality.db.DBController; import netneutrality.db.models.MTableModel; +import netneutrality.handler.LogHandler; public abstract class AbstractEntity implements EntityInterface { private final String primaryKey; @@ -21,14 +22,18 @@ public abstract class AbstractEntity implements EntityInterface { fillTableModel(); - if (!table.isEmpty()) - convertFromTableModel(table); + try { + if (!table.isEmpty()) + convertFromTableModel(table); + } catch (NullPointerException e) { + LogHandler.log("Table structure does not match expected variables", e); + } } private void fillTableModel() throws ArrayIndexOutOfBoundsException { StringBuilder whereClause = new StringBuilder(); for (String pk : getPrimaryKeys()) { - whereClause.append(pk + " = ?"); + whereClause.append(pk).append(" = ?"); //TODO: Fix last and if (getPrimaryKeys().length > 1) diff --git a/src/main/java/netneutrality/db/entities/OGuild.java b/src/main/java/netneutrality/db/entities/OGuild.java index 557dab0..14158b2 100644 --- a/src/main/java/netneutrality/db/entities/OGuild.java +++ b/src/main/java/netneutrality/db/entities/OGuild.java @@ -12,8 +12,9 @@ import netneutrality.db.models.MTableModel; public class OGuild extends AbstractEntity { private String guildID; - public boolean logging; - public String logchannel; + private boolean logging; + private boolean debug; + private String logchannel; private OGuildSetting settings; @@ -23,6 +24,18 @@ public class OGuild extends AbstractEntity { this.settings = new OGuildSetting(this); } + public boolean isLogging() { + return logging; + } + + public boolean isDebug() { + return debug; + } + + public String getLogchannel() { + return logchannel; + } + public void reloadSettings() { GuildManager.logger.debug("Reloading settings for guild: " + guildID); this.settings = new OGuildSetting(this); @@ -56,7 +69,8 @@ public class OGuild extends AbstractEntity { public void convertFromTableModel(MTableModel table) { this.guildID = (String) table.getRow(0).get(0); this.logging = ((Integer) table.getRow(0).get(1)) == 1; - this.logchannel = (String) table.getRow(0).get(2); + this.debug = ((Boolean) table.getRow(0).get(2)); + this.logchannel = (String) table.getRow(0).get(3); } } diff --git a/src/main/java/netneutrality/db/entities/OGuildSetting.java b/src/main/java/netneutrality/db/entities/OGuildSetting.java index c463c73..1c4aaf1 100644 --- a/src/main/java/netneutrality/db/entities/OGuildSetting.java +++ b/src/main/java/netneutrality/db/entities/OGuildSetting.java @@ -8,9 +8,7 @@ package netneutrality.db.entities;/* import netneutrality.db.models.MRowModel; import netneutrality.db.models.MTableModel; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class OGuildSetting extends AbstractEntity { private final OGuild guild; diff --git a/src/main/java/netneutrality/db/models/MTableModel.java b/src/main/java/netneutrality/db/models/MTableModel.java index 4766908..420f275 100644 --- a/src/main/java/netneutrality/db/models/MTableModel.java +++ b/src/main/java/netneutrality/db/models/MTableModel.java @@ -7,53 +7,69 @@ package netneutrality.db.models; * https://discord.gg/CdFcyQ */ -import java.util.Arrays; +import java.util.Collections; import java.util.LinkedList; import java.util.List; public class MTableModel { - private String name; + private final boolean emptyResult; + private final boolean success; + private final String name; private final List column; private final MRowsModel rows; - public MTableModel() { + this.emptyResult = true; + this.success = false; + this.name = null; + this.column = new LinkedList<>(); + this.rows = new MRowsModel(); + } + + public MTableModel(int success) { + this.emptyResult = true; + this.success = success > 0; this.name = null; this.column = new LinkedList<>(); this.rows = new MRowsModel(); } public MTableModel(String tableName) { + this.emptyResult = false; + this.success = true; this.name = tableName; this.column = new LinkedList<>(); this.rows = new MRowsModel(); } public MTableModel(String... columns) { + this.emptyResult = false; + this.success = true; this.name = null; this.column = new LinkedList<>(); this.rows = new MRowsModel(); - this.column.addAll(Arrays.asList(columns)); + Collections.addAll(column, columns); + } + + public boolean isEmptyResult() { + return emptyResult; + } + + public boolean isSuccess() { + return success; } public String getName() { return name; } - public void setName(String name) { - if (this.name != null) - this.name = name; - } - - public MTableModel addColumn(String name) { + public void addColumn(String name) { column.add(name); - return this; } - public MTableModel addRow(MRowModel row) { + public void addRow(MRowModel row) { rows.addRow(row); - return this; } public MRowsModel getRows() { @@ -96,4 +112,7 @@ public class MTableModel { public String toString() { return "Column: " + column + ", Rows (" + getNbRows() + "): " + rows; } + + + } diff --git a/src/main/java/netneutrality/handler/ConsoleHandler.java b/src/main/java/netneutrality/handler/ConsoleHandler.java deleted file mode 100644 index 6a489e0..0000000 --- a/src/main/java/netneutrality/handler/ConsoleHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -package netneutrality.handler; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -//TODO: To be replaced by HTTP API actions -public class ConsoleHandler { - - - private final static Logger logger = LoggerFactory.getLogger(ConsoleHandler.class); - public ConsoleHandler() { - logger.info("Console input ready!"); - } - - public String init() { - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - - String input = ""; - do { - System.out.print(">"); - try { - input = br.readLine(); - } catch (IOException e) { - e.printStackTrace(); - } - } while (!input.equalsIgnoreCase("quit")); - - return input; - } -} diff --git a/src/main/java/netneutrality/handler/LogHandler.java b/src/main/java/netneutrality/handler/LogHandler.java index 15585e9..2484813 100644 --- a/src/main/java/netneutrality/handler/LogHandler.java +++ b/src/main/java/netneutrality/handler/LogHandler.java @@ -6,12 +6,17 @@ package netneutrality.handler; * https://discord.gg/CdFcyQ */ +import netneutrality.GuildManager; +import netneutrality.MusicBot; import netneutrality.command.CommandContext; import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandExecutionException; +import netneutrality.utils.MessageFunction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.sql.SQLException; + public class LogHandler { private final static Logger logger = LoggerFactory.getLogger(LogHandler.class); @@ -27,24 +32,52 @@ public class LogHandler { sendMessageToChannel((CommandErrorException) e); } else if (e instanceof CommandExecutionException) { logInternally((CommandExecutionException) e); + tryLogToDebugChannel((CommandExecutionException) e); + } else if (e instanceof SQLException) { + logger.error(e.getMessage(), e); } else { logger.error(e.getMessage(), e); } } + public static void log(String s, Exception e) { + logger.error(s, e); + } + public static void logThread(Thread t, Throwable e) { - logger.error("Exception thrown in thread {}", t); + logger.error("Uncaught exception thrown in thread {}", t); log((Exception) e); } private static void logInternally(CommandExecutionException error) { CommandContext context = error.getCommandContext(); - logger.error("Exception thrown from command [{}] in guild [{}]: {}", context.getCommand().getCommand(), context.getGuild().getId(), error.getMessage(), error); + logger.error("Exception thrown from command [{}] in guild [{}]: {}", context.getCommand().getCommandName(), context.getGuild().getId(), error.getMessage(), error); + } + + private static void tryLogToAllChannels(SQLException error) { + + + } + + private static void tryLogToDebugChannel(CommandExecutionException error) { + CommandContext context = error.getCommandContext(); + + if (context.getGuild() != null) { + if (GuildManager.getManager(context.getGuild()).isDebugEnabled()) { + context.getGuild() + .getTextChannels() + .stream() + .filter(textChannel -> textChannel.getName().equals("debug") || textChannel.getName().equals("log")) + .forEach(textChannel -> textChannel.sendMessageEmbeds(MessageFunction.buildDebugMessage(context, error)).queue()); + } + } + } private static void sendMessageToChannel(CommandErrorException error) { CommandContext context = error.getCommandContext(); + logger.error("Exception thrown from command [{}] in guild [{}]: {}", context.getCommand().getCommandName(), context.getGuild().getId(), error.getMessage()); context.reply(error.getMessage()); } } diff --git a/src/main/java/netneutrality/handler/ServerJoinHandler.java b/src/main/java/netneutrality/handler/hooks/guilds/ServerJoinHandler.java similarity index 65% rename from src/main/java/netneutrality/handler/ServerJoinHandler.java rename to src/main/java/netneutrality/handler/hooks/guilds/ServerJoinHandler.java index a498130..a015db9 100644 --- a/src/main/java/netneutrality/handler/ServerJoinHandler.java +++ b/src/main/java/netneutrality/handler/hooks/guilds/ServerJoinHandler.java @@ -1,4 +1,4 @@ -package netneutrality.handler; +package netneutrality.handler.hooks.guilds; /* * Copyright (c) anthorob @@ -10,21 +10,18 @@ package netneutrality.handler; import net.dv8tion.jda.api.events.guild.GuildJoinEvent; import net.dv8tion.jda.api.events.guild.GuildLeaveEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import netneutrality.db.DBController; -import netneutrality.db.controllers.DBGuild; +import netneutrality.GuildManager; import org.jetbrains.annotations.NotNull; public class ServerJoinHandler extends ListenerAdapter { @Override public void onGuildJoin(@NotNull GuildJoinEvent event) { - ((DBGuild) DBController.get("guild")).insertGuildInDB(event.getGuild()); - + GuildManager.getManager(event.getGuild()).handleJoinEvent(); } @Override public void onGuildLeave(@NotNull GuildLeaveEvent event) { - ((DBGuild) DBController.get("guild")).removeGuildInDB(event.getGuild()); - + GuildManager.getManager(event.getGuild()).removeFromDB(); } } diff --git a/src/main/java/netneutrality/handler/message/EditHandler.java b/src/main/java/netneutrality/handler/hooks/message/EditHandler.java similarity index 98% rename from src/main/java/netneutrality/handler/message/EditHandler.java rename to src/main/java/netneutrality/handler/hooks/message/EditHandler.java index ff3f80d..c680058 100644 --- a/src/main/java/netneutrality/handler/message/EditHandler.java +++ b/src/main/java/netneutrality/handler/hooks/message/EditHandler.java @@ -1,4 +1,4 @@ -package netneutrality.handler.message; +package netneutrality.handler.hooks.message; /* * Copyright (c) anthorob diff --git a/src/main/java/netneutrality/handler/message/MessageReceivedHandler.java b/src/main/java/netneutrality/handler/hooks/message/MessageReceivedHandler.java similarity index 97% rename from src/main/java/netneutrality/handler/message/MessageReceivedHandler.java rename to src/main/java/netneutrality/handler/hooks/message/MessageReceivedHandler.java index f4a99a1..3e798b9 100644 --- a/src/main/java/netneutrality/handler/message/MessageReceivedHandler.java +++ b/src/main/java/netneutrality/handler/hooks/message/MessageReceivedHandler.java @@ -1,4 +1,4 @@ -package netneutrality.handler.message; +package netneutrality.handler.hooks.message; /* * Copyright (c) anthorob * @@ -30,11 +30,11 @@ public class MessageReceivedHandler extends ListenerAdapter { if (user.isBot()) return; if (event.isWebhookMessage()) return; + CommandContext context = CommandContext.createContext(event); + GuildManager.getManager(guild).getRateLimiter().check(member, message, channel); GuildManager.getManager(guild).checkAndLogMessage(message, member, channel); - CommandContext context = CommandContext.createContext(event); - String msg = message.getContentDisplay().trim(); if (msg.startsWith(Settings.getInstance().get("BOT_PREFIX", "$"))) { diff --git a/src/main/java/netneutrality/music/MusicManager.java b/src/main/java/netneutrality/music/MusicManager.java index 77424b8..368cfd7 100644 --- a/src/main/java/netneutrality/music/MusicManager.java +++ b/src/main/java/netneutrality/music/MusicManager.java @@ -11,6 +11,7 @@ import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; +import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeHttpContextFilter; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; @@ -19,6 +20,8 @@ import net.dv8tion.jda.api.entities.VoiceChannel; import netneutrality.ThreadManager; import netneutrality.command.CommandContext; import netneutrality.exceptions.CommandErrorException; +import netneutrality.thread.MusicPlayerAutoDisconnectThread; +import netneutrality.utils.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,11 +37,12 @@ public class MusicManager { private final static Logger logger = LoggerFactory.getLogger(MusicManager.class); private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager(); + private final static Map managers = new ConcurrentHashMap<>(); private final Guild guild; private final AudioPlayer player; private final TrackScheduler scheduler; - private final static Map managers = new ConcurrentHashMap<>(); + ScheduledExecutorService autoDisconnectThread; private MusicManager(Guild guild) { @@ -48,6 +52,8 @@ public class MusicManager { guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player)); player.addListener(scheduler); player.setVolume(15); + autoDisconnectThread = (ScheduledExecutorService) ThreadManager.getExecutor("music-disconnect", ThreadManager.ExecutorType.SCHEDULED); + autoDisconnectThread.scheduleWithFixedDelay(new MusicPlayerAutoDisconnectThread(this), 120, 120, TimeUnit.SECONDS); managers.put(guild.getId(), this); } @@ -60,25 +66,22 @@ public class MusicManager { } } - public static void registerSources() { + public static void initPlayerManager() { AudioSourceManagers.registerRemoteSources(playerManager); + + YoutubeHttpContextFilter.setPAPISID(Settings.getInstance().get("BOT_PAPISID", "")); + YoutubeHttpContextFilter.setPSID(Settings.getInstance().get("BOT_PSID", "")); } public boolean isConnectedTo(VoiceChannel vChannel) { return vChannel != null && vChannel.equals(guild.getAudioManager().getConnectedChannel()); } - public synchronized void connect(VoiceChannel vChannel) { + public void connect(VoiceChannel vChannel) { if (vChannel != null && !isConnectedTo(vChannel)) { guild.getAudioManager().openAudioConnection(vChannel); - - ((ScheduledExecutorService) ThreadManager.getExecutor("music", ThreadManager.ExecutorType.SCHEDULED)).scheduleWithFixedDelay(() -> { - if ((getCurrentlyPlaying() == null && scheduler.getQueue().isEmpty()) || vChannel.getMembers().size() == 0) { - leave(); - } - }, 120, 120, TimeUnit.SECONDS); } else { - logger.error("Error connecting!"); + throw new RuntimeException("Error connecting to voice channel"); } } @@ -96,6 +99,10 @@ public class MusicManager { return info.getRequester(); } + public Guild getGuild() { + return guild; + } + public void leave() { if (isConnected()) { player.stopTrack(); @@ -103,7 +110,6 @@ public class MusicManager { } scheduler.resetTopic(); - System.out.println(scheduler.getQueue().size()); } public static void disconnectPlayers() { @@ -133,7 +139,6 @@ public class MusicManager { } VoiceChannel vChannel = member.getVoiceState().getChannel(); - if (needToBeConnected && !isConnectedTo(vChannel)) { throw new CommandErrorException("Not in your voice channel", context, null); } @@ -168,29 +173,33 @@ public class MusicManager { public void voteSkip(CommandContext context) { Queue queue = scheduler.getQueue(); VoiceChannel voiceChannel = guild.getAudioManager().getConnectedChannel(); + TrackScheduler.TrackInfo info = queue.peek(); if (getCurrentlyPlaying() == null) { return; } + if (info == null) { + return; + } + // Minus the bot itself int connected = voiceChannel.getMembers().size() - 1; - if (connected > 2) { - TrackScheduler.TrackInfo info = queue.peek(); + if (connected > 2) { double needed = connected / 2.1; - if (info != null) { - info.toggleSkip(context.getGuildUser()); + info.toggleSkip(context.getGuildUser()); - if (info.getSkips().size() > needed) { - skip(1); - } else { - context.reply(String.format("Current skips: %d/%f", info.getSkips().size(), Math.ceil(needed))); - } + if (info.getSkips().size() > needed) { + context.reply("Skipping current track: %s", info.getTrack().getInfo().title); + skip(1); + } else { + context.reply("Current skips: %d/%d", info.getSkips().size(), (int) Math.ceil(needed)); } } else { + context.reply("Skipping current track since not enough people are connected to the voice channel."); skip(1); } } diff --git a/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java b/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java new file mode 100644 index 0000000..9c19ba3 --- /dev/null +++ b/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java @@ -0,0 +1,41 @@ +package netneutrality.thread;/* + * Copyright (c) anthorob + * + * https://xtremcommunity.com/ + * https://discord.gg/CdFcyQ + */ + +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.VoiceChannel; +import netneutrality.MusicBot; +import netneutrality.music.MusicManager; + +import java.util.List; + +public class MusicPlayerAutoDisconnectThread implements Runnable { + + MusicManager manager; + + public MusicPlayerAutoDisconnectThread(MusicManager musicManager) { + manager = musicManager; + } + + @Override + public void run() { + Guild guild = manager.getGuild(); + VoiceChannel channel = guild.getAudioManager().getConnectedChannel(); + + if (manager.getCurrentlyPlaying() == null && manager.getScheduler().getQueue().isEmpty()) { + manager.leave(); + return; + } + + if (channel != null) { + List members = channel.getMembers().stream().filter(member -> !member.getId().equals(MusicBot.getSelf().getId())).toList(); + + if (members.size() == 0) + manager.leave(); + } + } +} diff --git a/src/main/java/netneutrality/utils/MessageFunction.java b/src/main/java/netneutrality/utils/MessageFunction.java index d198d13..18d13ea 100644 --- a/src/main/java/netneutrality/utils/MessageFunction.java +++ b/src/main/java/netneutrality/utils/MessageFunction.java @@ -17,10 +17,12 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.*; import netneutrality.command.AbstractCommand; +import netneutrality.command.CommandContext; import netneutrality.command.CommandType; import netneutrality.db.DBController; import netneutrality.db.controllers.DBBlacklist; import netneutrality.db.models.MBlacklist; +import netneutrality.exceptions.CommandExecutionException; import netneutrality.music.MusicManager; import org.apache.commons.lang3.time.DurationFormatUtils; import org.slf4j.Logger; @@ -179,7 +181,7 @@ public class MessageFunction { message.setColor(Color.GREEN); } - message.addField(String.format("%s%s %s %s", Settings.getInstance().get("BOT_PREFIX"), command.getCommand(), availAlias, usage), description, false); + message.addField(String.format("%s%s %s %s", Settings.getInstance().get("BOT_PREFIX"), command.getCommandName(), availAlias, usage), description, false); } } @@ -190,6 +192,21 @@ public class MessageFunction { return messages; } + public static MessageEmbed buildDebugMessage(CommandContext context, CommandExecutionException error) { + EmbedBuilder message = new EmbedBuilder(); + message.setColor(Color.RED); + message.setTitle(":warning: Exception in command execution"); + message.addField("Caused by command:", context.getCommand().getCommandName(), false); + message.addField("Exception:", error.getMessage(), false); + if (error.getCause() != null) { + message.addField("Caused by:", error.getCause().getMessage(), false); + } + message.setFooter("Requested by " + context.getDiscordUser().getName(), context.getDiscordUser().getAvatarUrl()); + message.setTimestamp(OffsetDateTime.now()); + + return message.build(); + } + public static void checkBlacklist(Guild guild, Message message, TextChannel channel) { ((DBBlacklist) DBController.get("blacklist")).getBlacklistFromServer(guild.getId(), mBlacklists -> { @@ -211,4 +228,6 @@ public class MessageFunction { }); } + + } diff --git a/src/main/java/netneutrality/utils/Settings.java b/src/main/java/netneutrality/utils/Settings.java index fad2544..0179810 100644 --- a/src/main/java/netneutrality/utils/Settings.java +++ b/src/main/java/netneutrality/utils/Settings.java @@ -67,13 +67,4 @@ public class Settings { return get("BOT_OWNER"); } - public String getOwnerGuild() { - return get("BOT_OWNERGUILD"); - } - - public String getLogChannel() { - return get("BOT_ERRORCHANNEL"); - } - - }