Use a fork of lavaplayer to play age-restricted content on Youtube

This commit is contained in:
anthorob committed 2022-02-17 20:09:41 -05:00
1 parent 048b645e61
commit d849b80b7b
50 files changed
+404 -339

No files matched your search

+2 -2
View File
@@ -1,8 +1,8 @@
BOT_TOKEN= BOT_TOKEN=
BOT_PREFIX= BOT_PREFIX=
BOT_OWNER= BOT_OWNER=
BOT_OWNERGUILD= BOT_PAPISID=
BOT_ERRORCHANNEL= BOT_PSID=
MYSQL_HOST= MYSQL_HOST=
MYSQL_USER= MYSQL_USER=
+15 -5
View File
@@ -91,6 +91,11 @@
<url>https://m2.dv8tion.net/releases</url> <url>https://m2.dv8tion.net/releases</url>
</repository> </repository>
<repository>
<id>jitpack</id>
<url>https://jitpack.io</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
@@ -99,6 +104,16 @@
<artifactId>JDA</artifactId> <artifactId>JDA</artifactId>
<version>4.4.0_350</version> <version>4.4.0_350</version>
</dependency> </dependency>
<!-- <dependency>-->
<!-- <groupId>com.sedmelluq</groupId>-->
<!-- <artifactId>lavaplayer</artifactId>-->
<!-- <version>1.3.78</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.github.walkyst</groupId>
<artifactId>lavaplayer-fork</artifactId>
<version>1.3.97</version>
</dependency>
<dependency> <dependency>
<groupId>com.squareup.okhttp3</groupId> <groupId>com.squareup.okhttp3</groupId>
@@ -145,11 +160,6 @@
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.12.0</version> <version>3.12.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.sedmelluq</groupId>
<artifactId>lavaplayer</artifactId>
<version>1.3.78</version>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
+1
View File
@@ -0,0 +1 @@
ALTER TABLE `guilds` ADD `debug` BOOLEAN NOT NULL DEFAULT '1' AFTER `logging`;
+48 -21
View File
@@ -10,6 +10,8 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.entities.TextChannel;
import netneutrality.db.DBController;
import netneutrality.db.controllers.DBGuild;
import netneutrality.db.entities.OGuild; import netneutrality.db.entities.OGuild;
import netneutrality.handler.ratelimiter.IMessageRateLimiter; import netneutrality.handler.ratelimiter.IMessageRateLimiter;
import netneutrality.handler.ratelimiter.MessageRateLimiterImpl; import netneutrality.handler.ratelimiter.MessageRateLimiterImpl;
@@ -23,7 +25,9 @@ import java.util.concurrent.ConcurrentHashMap;
public class GuildManager { public class GuildManager {
public enum GuildSetting { 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 setting;
private final String defaultValue; private final String defaultValue;
@@ -58,6 +62,8 @@ public class GuildManager {
private GuildManager(Guild guild) { private GuildManager(Guild guild) {
this.guild = guild; this.guild = guild;
handleJoinEvent();
this.guildEntity = new OGuild(guild.getId()); this.guildEntity = new OGuild(guild.getId());
this.rateLimiter = new MessageRateLimiterImpl(); this.rateLimiter = new MessageRateLimiterImpl();
@@ -72,14 +78,40 @@ public class GuildManager {
} }
} }
// Getter
public static Map<String, GuildManager> getManagers() {
return managers;
}
public static GuildManager getManager(String guildId) { public static GuildManager getManager(String guildId) {
return managers.getOrDefault(guildId, null); return managers.getOrDefault(guildId, null);
} }
public static Map<String, GuildManager> getManagers() { public String getSetting(GuildSetting key) {
return managers; return guildEntity.getSettings().getSettingByKey(key.toString());
} }
public boolean isLoggingEnabled() {
return guildEntity.isLogging();
}
public boolean isDebugEnabled() {
return guildEntity.isDebug();
}
public Map<String, String> getSettings() {
return guildEntity.getSettings().getSettings();
}
public IMessageRateLimiter getRateLimiter() {
return rateLimiter;
}
public Guild getGuild() {
return guild;
}
public static boolean reloadSettingsForGuild(String guildId) { public static boolean reloadSettingsForGuild(String guildId) {
if (managers.containsKey(guildId)) { if (managers.containsKey(guildId)) {
GuildManager manager = managers.get(guildId); GuildManager manager = managers.get(guildId);
@@ -111,33 +143,28 @@ public class GuildManager {
MessageFunction.checkBlacklist(guild, message, channel); MessageFunction.checkBlacklist(guild, message, channel);
} }
public String getSetting(String key) { public boolean existInDb() {
return guildEntity.getSettings().getSettingByKey(key); return DBController.get().exists("guilds", "guild_id", guild.getId());
}
public String getSetting(GuildSetting key) {
return guildEntity.getSettings().getSettingByKey(key.toString());
}
public Map<String, String> getSettings() {
return guildEntity.getSettings().getSettings();
} }
public void reloadSettings() { public void reloadSettings() {
guildEntity.reloadSettings(); guildEntity.reloadSettings();
} }
public IMessageRateLimiter getRateLimiter() { public void handleJoinEvent() {
return rateLimiter; if (!existInDb()) {
((DBGuild) DBController.get("guild")).insertGuildInDB(guild);
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 Guild getGuild() {
return guild;
} }
public void removeFromDB() {
((DBGuild) DBController.get("guild")).removeGuildInDB(guild);
private void load() {
} }
} }
+11 -4
View File
@@ -3,13 +3,14 @@ package netneutrality;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.requests.GatewayIntent;
import netneutrality.command.CommandManager; import netneutrality.command.CommandManager;
import netneutrality.db.DBController; import netneutrality.db.DBController;
import netneutrality.handler.message.EditHandler; import netneutrality.handler.hooks.message.EditHandler;
import netneutrality.handler.message.MessageReceivedHandler; import netneutrality.handler.hooks.message.MessageReceivedHandler;
import netneutrality.handler.ServerJoinHandler; import netneutrality.handler.hooks.guilds.ServerJoinHandler;
import netneutrality.http.server.WebApi; import netneutrality.http.server.WebApi;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.thread.BaseThreadFactory; import netneutrality.thread.BaseThreadFactory;
@@ -29,10 +30,11 @@ public class MusicBot {
public static void main(String[] args) { public static void main(String[] args) {
DBController.init(); DBController.init();
initJDA(); initJDA();
CommandManager.init(); CommandManager.init();
MusicManager.registerSources(); MusicManager.initPlayerManager();
jda.getPresence().setActivity(Activity.watching("me load...")); jda.getPresence().setActivity(Activity.watching("me load..."));
jda.addEventListener(new MessageReceivedHandler(), new EditHandler(), new ServerJoinHandler()); jda.addEventListener(new MessageReceivedHandler(), new EditHandler(), new ServerJoinHandler());
@@ -66,6 +68,11 @@ public class MusicBot {
return jda; return jda;
} }
public static User getSelf() {
return jda.getSelfUser();
}
private static void disconnect() { private static void disconnect() {
if (jda != null) { if (jda != null) {
jda.shutdown(); jda.shutdown();
+3 -16
View File
@@ -25,27 +25,14 @@ public class ThreadManager {
ExecutorService executor; ExecutorService executor;
switch (type) { switch (type) {
case FIXED: case FIXED -> executor = executors.computeIfAbsent(name, s -> Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new BaseThreadFactory(name)));
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)));
break; default -> executor = executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThreadFactory(name)));
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)));
} }
return executor; return executor;
} }
public static Future<?> dispatch(ExecutorService executor, Runnable task) {
return executor.submit(task);
}
public static <T> Future<T> dispatch(ExecutorService executor, Callable<T> task) {
return executor.submit(task);
}
public static void shutdownExecutor() { public static void shutdownExecutor() {
System.out.println("[Executor] Shutting down..."); System.out.println("[Executor] Shutting down...");
@@ -20,7 +20,7 @@ public abstract class AbstractCommand implements ICommand {
* *
* @return the name of the command. * @return the name of the command.
*/ */
public abstract String getCommand(); public abstract String getCommandName();
/** /**
* @return all the aliases the command has * @return all the aliases the command has
@@ -10,6 +10,8 @@ import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import netneutrality.ThreadManager; import netneutrality.ThreadManager;
import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandExecutionException;
import netneutrality.handler.LogHandler; import netneutrality.handler.LogHandler;
import netneutrality.utils.Settings; import netneutrality.utils.Settings;
import netneutrality.utils.UserFunction; import netneutrality.utils.UserFunction;
@@ -108,6 +110,10 @@ public class CommandContext {
} }
} }
public void reply(String format, Object... arguments) {
reply(String.format(format, arguments));
}
public void reply(Message msg) { public void reply(Message msg) {
if (channel != null) { if (channel != null) {
channel.sendMessage(msg).queue(); channel.sendMessage(msg).queue();
@@ -142,6 +148,7 @@ public class CommandContext {
this.command = command; this.command = command;
//TODO: Add usage check //TODO: Add usage check
try {
if (command.needAdmin()) { if (command.needAdmin()) {
if (!UserFunction.isAdmin(member)) { if (!UserFunction.isAdmin(member)) {
return; return;
@@ -149,13 +156,12 @@ public class CommandContext {
} }
if (command.canBeExecutedBy(guild, member)) { if (command.canBeExecutedBy(guild, member)) {
try {
command.execute(this); 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));
} }
} }
} }
@@ -44,8 +44,8 @@ public class CommandManager {
if (!command.isEnabled()) if (!command.isEnabled())
continue; continue;
if (!commands.containsKey(command.getCommand())) { if (!commands.containsKey(command.getCommandName())) {
commands.put(command.getCommand(), command); commands.put(command.getCommandName(), command);
} }
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) { | InvocationTargetException | NoSuchMethodException | SecurityException e) {
@@ -30,7 +30,7 @@ public class HelpCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "help"; return "help";
} }
@@ -24,7 +24,7 @@ public class PingCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "ping"; return "ping";
} }
@@ -22,7 +22,7 @@ public class ConfigureCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "configure"; return "configure";
} }
@@ -34,7 +34,7 @@ public class BitcoinPriceCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "bitcoin"; return "bitcoin";
} }
@@ -33,7 +33,7 @@ public class CryptoPriceCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "crypto"; return "crypto";
} }
@@ -34,7 +34,7 @@ public class EthereumPriceCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "ethereum"; return "ethereum";
} }
@@ -34,7 +34,7 @@ public class LitecoinPriceCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "litecoin"; return "litecoin";
} }
@@ -12,6 +12,7 @@ import netneutrality.command.CommandType;
import netneutrality.db.DBController; import netneutrality.db.DBController;
import netneutrality.db.controllers.DBBlacklist; import netneutrality.db.controllers.DBBlacklist;
import netneutrality.db.models.MBlacklist; import netneutrality.db.models.MBlacklist;
import netneutrality.exceptions.CommandExecutionException;
public class BlacklistCommand extends AbstractCommand { public class BlacklistCommand extends AbstractCommand {
@@ -26,7 +27,7 @@ public class BlacklistCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "blacklist"; return "blacklist";
} }
@@ -53,6 +54,11 @@ public class BlacklistCommand extends AbstractCommand {
@Override @Override
public void execute(CommandContext context) { public void execute(CommandContext context) {
String[] args = context.getArgumentsAsArray(); 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) { if (args.length > 0 && args.length < 3) {
String word = (args.length == 2 ? args[1] : ""); 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 -> { context.getChannel().sendMessage("Retrieving list, please wait...").queue(t -> {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
((DBBlacklist) DBController.get("blacklist")).getBlacklistFromServer(context.getGuild().getId(), mBlacklists -> { controller.getBlacklistFromServer(context.getGuild().getId(), mBlacklists -> {
for (MBlacklist bl : mBlacklists) { for (MBlacklist bl : mBlacklists) {
sb.append(bl.getWord()).append(" -> ").append(bl.isEnabled() ? "enabled" : "disabled").append("\n"); sb.append(bl.getWord()).append(" -> ").append(bl.isEnabled() ? "enabled" : "disabled").append("\n");
} }
@@ -77,48 +83,40 @@ public class BlacklistCommand extends AbstractCommand {
case "add": case "add":
((DBBlacklist) DBController.get("blacklist")).add(new MBlacklist(word, true, context.getDiscordUser().getId(), context.getGuild().getId()), response -> { if (controller.add(new MBlacklist(word, true, context.getDiscordUser().getId(), context.getGuild().getId()))) {
if (response) { context.reply(String.format("Added the word [%s] to the blacklist.", word));
context.getChannel().sendMessage("Added the word \"" + word + "\" to the blacklist.").queue();
} else { } else {
context.getChannel().sendMessage("Error adding \"" + word + "\" to the blacklist. It's already blacklisted!").queue(); context.reply(String.format("Error adding [%s] to the blacklist. It's already blacklisted!", word));
} }
});
break; break;
case "remove": case "remove":
((DBBlacklist) DBController.get("blacklist")).delete(word, context.getGuild().getId(), success -> { if (controller.delete(word, context.getGuild().getId())) {
if (success) {
context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue();
} else { } else {
context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue();
} }
});
break; break;
case "disable": case "disable":
((DBBlacklist) DBController.get("blacklist")).disable(word, context.getGuild().getId(), success -> { if (controller.disable(word, context.getGuild().getId())) {
if (success) {
context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue();
} else { } else {
context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue();
} }
});
break; break;
case "enable": case "enable":
((DBBlacklist) DBController.get("blacklist")).enable(word, context.getGuild().getId(), success -> { if (controller.enable(word, context.getGuild().getId())) {
if (success) {
context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue();
} else { } else {
context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue();
} }
});
break; break;
@@ -24,7 +24,7 @@ public class PruneCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "prune"; return "prune";
} }
@@ -20,7 +20,7 @@ public class BitconnectCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "bitconnect"; return "bitconnect";
} }
@@ -22,7 +22,7 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "playing"; return "playing";
} }
@@ -24,7 +24,7 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "deletequeue"; return "deletequeue";
} }
@@ -10,6 +10,8 @@ package netneutrality.command.music;
import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.entities.VoiceChannel;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandExecutionException;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils; import netneutrality.utils.MusicUtils;
@@ -21,7 +23,7 @@ public class JoinCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "join"; return "join";
} }
@@ -43,7 +45,18 @@ public class JoinCommand extends AbstractMusicCommand {
@Override @Override
public void execute(CommandContext context) { public void execute(CommandContext context) {
MusicManager player = MusicManager.get(context.getGuild()); 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(); VoiceChannel vChannel = context.getGuildUser().getVoiceState().getChannel();
player.connect(vChannel); player.connect(vChannel);
@@ -24,7 +24,7 @@ public class LeaveCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "leave"; return "leave";
} }
@@ -19,7 +19,7 @@ public class PlayCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "play"; return "play";
} }
@@ -24,7 +24,7 @@ public class SkipCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "skip"; return "skip";
} }
@@ -21,7 +21,7 @@ public class StopCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "stop"; return "stop";
} }
@@ -26,7 +26,7 @@ public class ViewQueueCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "viewqueue"; return "viewqueue";
} }
@@ -26,7 +26,7 @@ public class VolumeCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "volume"; return "volume";
} }
@@ -19,7 +19,7 @@ public class VoteSkipCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "voteskip"; return "voteskip";
} }
@@ -34,7 +34,7 @@ public class DatabaseCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "database"; return "database";
} }
@@ -31,7 +31,7 @@ public class EvalMethod extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "evaluate"; return "evaluate";
} }
@@ -23,7 +23,7 @@ public class LoggingCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "logging"; return "logging";
} }
@@ -30,7 +30,7 @@ public class SellyCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "selly"; return "selly";
} }
@@ -24,7 +24,7 @@ public class TestCommand extends AbstractCommand {
} }
@Override @Override
public String getCommand() { public String getCommandName() {
return "test"; return "test";
} }
@@ -37,70 +37,34 @@ public class AsyncMySqlAction {
} }
public void async(Consumer<MTableModel> success) { public void async(Consumer<MTableModel> success) {
switch (type) { switch (type) {
case INSERT: case INSERT -> executor.submit(() -> success.accept(new MTableModel(db.insert(this.sqlString, this.params))));
ThreadManager.dispatch(executor, () -> { case UPDATE -> executor.submit(() -> success.accept(new MTableModel(db.update(this.sqlString, this.params))));
db.insert(this.sqlString, this.params); case DELETE -> executor.submit(() -> success.accept(new MTableModel(db.delete(this.sqlString, this.params))));
}); case SELECT -> executor.submit(() -> {
break;
case UPDATE:
ThreadManager.dispatch(executor, () -> {
db.update(this.sqlString, this.params);
});
break;
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); ResultSet result = db.prepareAndExecute(this.sqlString, this.params);
MTableModel table = MysqlDatabase.convertToTableModel(result, tableName);
success.accept(table); success.accept(MysqlDatabase.convertToTableModel(result, tableName));
}); });
break;
} }
} }
public MTableModel blocking() { public MTableModel blocking() {
MTableModel table = new MTableModel();
try { try {
switch (type) { table = switch (type) {
case INSERT: case INSERT -> executor.submit(() -> new MTableModel(db.insert(this.sqlString, this.params))).get();
ThreadManager.dispatch(executor, () -> { case UPDATE -> executor.submit(() -> new MTableModel(db.update(this.sqlString, this.params))).get();
db.insert(this.sqlString, this.params); case DELETE -> executor.submit(() -> new MTableModel(db.delete(this.sqlString, this.params))).get();
}).get(); case SELECT -> executor.submit(() -> db.prepareAndExecute(this.sqlString, this.tableName, this.params)).get();
};
case UPDATE: } catch (InterruptedException | ExecutionException e) {
ThreadManager.dispatch(executor, () -> { return table;
db.update(this.sqlString, this.params); }
}).get();
case DELETE:
ThreadManager.dispatch(executor, () -> {
db.delete(this.sqlString, this.params);
}).get();
case SELECT:
Callable<MTableModel> task = () -> {
ResultSet result = db.prepareAndExecute(this.sqlString, this.params);
MTableModel table = MysqlDatabase.convertToTableModel(result, tableName);
return table; return table;
};
Future<MTableModel> future = ThreadManager.dispatch(executor, task);
return future.get();
} }
} catch (InterruptedException | ExecutionException e) {
return null;
}
return null;
}
} }
@@ -10,11 +10,10 @@ import java.sql.Timestamp;
import java.sql.Types; import java.sql.Types;
import java.util.Calendar; import java.util.Calendar;
import netneutrality.MusicBot;
import netneutrality.db.entities.EntityInterface;
import netneutrality.db.models.MRowModel; import netneutrality.db.models.MRowModel;
import netneutrality.db.models.MTableModel; import netneutrality.db.models.MTableModel;
import netneutrality.exceptions.UnimplementedParameterException; import netneutrality.exceptions.UnimplementedParameterException;
import netneutrality.handler.LogHandler;
import netneutrality.utils.Settings; import netneutrality.utils.Settings;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -22,6 +21,7 @@ import org.slf4j.LoggerFactory;
public class MysqlDatabase { public class MysqlDatabase {
private final static Logger logger = LoggerFactory.getLogger(MysqlDatabase.class); private final static Logger logger = LoggerFactory.getLogger(MysqlDatabase.class);
private final static Object dmlLock = new Object();
protected Connection connection; protected Connection connection;
private final String dbName; private final String dbName;
@@ -37,8 +37,11 @@ public class MysqlDatabase {
public static CommandType stringToType(String str) { public static CommandType stringToType(String str) {
return CommandType.valueOf(str); return CommandType.valueOf(str);
} }
}
public String getType() {
return type;
}
}
protected MysqlDatabase(String dbName) { protected MysqlDatabase(String dbName) {
this.dbName = dbName; this.dbName = dbName;
@@ -51,7 +54,7 @@ public class MysqlDatabase {
connection = new MysqlConnector(dbName, dbUser, dbHost, dbPass).connect().getConnection(); connection = new MysqlConnector(dbName, dbUser, dbHost, dbPass).connect().getConnection();
} catch (SQLException e) { } catch (SQLException e) {
logger.error("Error connecting to database. Shutting down..", 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(); stmt = connection.createStatement();
return stmt.executeQuery(query); return stmt.executeQuery(query);
} catch (SQLException e) { } catch (SQLException e) {
logger.error(e.toString()); LogHandler.log(e);
} }
return null; return null;
@@ -80,9 +83,8 @@ public class MysqlDatabase {
* *
* @param sql The SQL query to execute * @param sql The SQL query to execute
* @param params The parameters to include in the query * @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); return executeUpdate(sql, params);
} }
@@ -94,7 +96,7 @@ public class MysqlDatabase {
* @param params The parameters to include in the query * @param params The parameters to include in the query
* @return an integer of how many row were affected * @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); return executeUpdate(sql, params);
} }
@@ -106,29 +108,31 @@ public class MysqlDatabase {
* @param params The parameters to include in the query * @param params The parameters to include in the query
* @return an integer of how many row were affected * @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); return executeUpdate(sql, params);
} }
public boolean exists(String table, String key, String value) { private int executeUpdate(String sql, Object[] params) {
return prepareAndExecuteAsync("SELECT 1 FROM " + table + " WHERE " + key + " = ?", value).blocking().isEmpty();
}
private synchronized int executeUpdate(String sql, Object[] params) {
logger.debug("Query: " + sql); logger.debug("Query: " + sql);
synchronized (dmlLock) {
try { try {
PreparedStatement query = connection.prepareStatement(sql); PreparedStatement query = connection.prepareStatement(sql);
resolveParameters(query, params); resolveParameters(query, params);
return query.executeUpdate(); return query.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); LogHandler.log(e);
} }
return -1; 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();
}
/** /**
* Execute a SELECT statement with the specified parameters. * 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 ? * In the SQL query, where there is a parameter to be included, you need to replace it with ?
@@ -137,13 +141,25 @@ public class MysqlDatabase {
* @param params The parameters to include in the query * @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)} * @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 { try {
PreparedStatement query = connection.prepareStatement(sql); PreparedStatement query = connection.prepareStatement(sql);
resolveParameters(query, params); resolveParameters(query, params);
ResultSet rs = query.executeQuery(); return query.executeQuery();
return rs; } catch (SQLException e) {
logger.error(e.getMessage(), e);
}
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) { } catch (SQLException e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
@@ -206,8 +222,6 @@ public class MysqlDatabase {
/** /**
* Close the MySQL connection * Close the MySQL connection
*
* @throws SQLException
*/ */
public void close() throws SQLException { public void close() throws SQLException {
System.out.println("Closing database..."); System.out.println("Closing database...");
@@ -249,8 +263,7 @@ public class MysqlDatabase {
* @return a {@link MTableModel} with the appropriate column and rows * @return a {@link MTableModel} with the appropriate column and rows
*/ */
protected static MTableModel convertToTableModel(ResultSet rs, String tableName) { protected static MTableModel convertToTableModel(ResultSet rs, String tableName) {
MTableModel table = new MTableModel(); MTableModel table = new MTableModel(tableName);
table.setName(tableName);
try { try {
ResultSetMetaData metadata = rs.getMetaData(); ResultSetMetaData metadata = rs.getMetaData();
@@ -14,77 +14,36 @@ public class DBBlacklist extends AbstractController {
private final Logger logger = LoggerFactory.getLogger(DBBlacklist.class); private final Logger logger = LoggerFactory.getLogger(DBBlacklist.class);
public void add(MBlacklist obj, Consumer<Boolean> success) { public boolean add(MBlacklist obj) {
isAlreadyBlacklisted(obj.getWord(), obj.getServerId(), blacklisted -> { if (!isAlreadyBlacklisted(obj.getWord(), obj.getServerId())) {
if (blacklisted == 0) { return database.prepareAndExecuteAsync("INSERT INTO blacklist VALUES(?,?,?,?)", obj.getServerId(), obj.getWord(), obj.isEnabled(), obj.getCreatorId()).blocking().isSuccess();
database.prepareAndExecuteAsync("INSERT INTO blacklist VALUES(?,?,?,?)", obj.getServerId(), obj.getWord(), obj.isEnabled(), obj.getCreatorId()).async();
success.accept(true);
} else {
success.accept(false);
}
});
} }
return false;
public void delete(String word, String serverId, Consumer<Boolean> 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);
}
});
} }
public void enable(String word, String serverId, Consumer<Boolean> success) { public boolean delete(String word, String serverId) {
if (isAlreadyBlacklisted(word, serverId)) {
isAlreadyBlacklisted(word, serverId, blacklisted -> { return database.prepareAndExecuteAsync("DELETE FROM blacklist WHERE word = ? AND guild_id = ?", word, serverId).blocking().isSuccess();
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 void disable(String word, String serverId, Consumer<Boolean> success) { return false;
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 boolean enable(String word, String serverId) {
public void getBlacklistForWord(String word, String serverId, Consumer<MBlacklist> success) { if (isAlreadyBlacklisted(word, serverId)) {
return database.prepareAndExecuteAsync("UPDATE blacklist SET enabled = 1 WHERE word = ? AND guild_id = ?", word, serverId).blocking().isSuccess();
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);
})); return false;
}
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<ArrayList<MBlacklist>> success) { public void getBlacklistFromServer(String serverId, Consumer<ArrayList<MBlacklist>> success) {
@@ -104,7 +63,6 @@ public class DBBlacklist extends AbstractController {
} }
@Deprecated
public ArrayList<MBlacklist> getBlacklistFromServer(String serverId) { public ArrayList<MBlacklist> getBlacklistFromServer(String serverId) {
MTableModel model = database.prepareAndExecuteAsync("SELECT * FROM blacklist WHERE guild_id = ? AND enabled = 1", serverId).blocking(); 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; return false;
} }
private void isAlreadyBlacklisted(String word, String serverId, Consumer<Integer> 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 @Override
public String getControllerName() { public String getControllerName() {
return "blacklist"; return "blacklist";
@@ -8,6 +8,7 @@ package netneutrality.db.entities;/*
import netneutrality.MusicBot; import netneutrality.MusicBot;
import netneutrality.db.DBController; import netneutrality.db.DBController;
import netneutrality.db.models.MTableModel; import netneutrality.db.models.MTableModel;
import netneutrality.handler.LogHandler;
public abstract class AbstractEntity implements EntityInterface { public abstract class AbstractEntity implements EntityInterface {
private final String primaryKey; private final String primaryKey;
@@ -21,14 +22,18 @@ public abstract class AbstractEntity implements EntityInterface {
fillTableModel(); fillTableModel();
try {
if (!table.isEmpty()) if (!table.isEmpty())
convertFromTableModel(table); convertFromTableModel(table);
} catch (NullPointerException e) {
LogHandler.log("Table structure does not match expected variables", e);
}
} }
private void fillTableModel() throws ArrayIndexOutOfBoundsException { private void fillTableModel() throws ArrayIndexOutOfBoundsException {
StringBuilder whereClause = new StringBuilder(); StringBuilder whereClause = new StringBuilder();
for (String pk : getPrimaryKeys()) { for (String pk : getPrimaryKeys()) {
whereClause.append(pk + " = ?"); whereClause.append(pk).append(" = ?");
//TODO: Fix last and //TODO: Fix last and
if (getPrimaryKeys().length > 1) if (getPrimaryKeys().length > 1)
@@ -12,8 +12,9 @@ import netneutrality.db.models.MTableModel;
public class OGuild extends AbstractEntity { public class OGuild extends AbstractEntity {
private String guildID; private String guildID;
public boolean logging; private boolean logging;
public String logchannel; private boolean debug;
private String logchannel;
private OGuildSetting settings; private OGuildSetting settings;
@@ -23,6 +24,18 @@ public class OGuild extends AbstractEntity {
this.settings = new OGuildSetting(this); this.settings = new OGuildSetting(this);
} }
public boolean isLogging() {
return logging;
}
public boolean isDebug() {
return debug;
}
public String getLogchannel() {
return logchannel;
}
public void reloadSettings() { public void reloadSettings() {
GuildManager.logger.debug("Reloading settings for guild: " + guildID); GuildManager.logger.debug("Reloading settings for guild: " + guildID);
this.settings = new OGuildSetting(this); this.settings = new OGuildSetting(this);
@@ -56,7 +69,8 @@ public class OGuild extends AbstractEntity {
public void convertFromTableModel(MTableModel table) { public void convertFromTableModel(MTableModel table) {
this.guildID = (String) table.getRow(0).get(0); this.guildID = (String) table.getRow(0).get(0);
this.logging = ((Integer) table.getRow(0).get(1)) == 1; 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);
} }
} }
@@ -8,9 +8,7 @@ package netneutrality.db.entities;/*
import netneutrality.db.models.MRowModel; import netneutrality.db.models.MRowModel;
import netneutrality.db.models.MTableModel; import netneutrality.db.models.MTableModel;
import java.util.HashMap; import java.util.*;
import java.util.List;
import java.util.Map;
public class OGuildSetting extends AbstractEntity { public class OGuildSetting extends AbstractEntity {
private final OGuild guild; private final OGuild guild;
@@ -7,53 +7,69 @@ package netneutrality.db.models;
* https://discord.gg/CdFcyQ * https://discord.gg/CdFcyQ
*/ */
import java.util.Arrays; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
public class MTableModel { public class MTableModel {
private String name; private final boolean emptyResult;
private final boolean success;
private final String name;
private final List<String> column; private final List<String> column;
private final MRowsModel rows; private final MRowsModel rows;
public MTableModel() { 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.name = null;
this.column = new LinkedList<>(); this.column = new LinkedList<>();
this.rows = new MRowsModel(); this.rows = new MRowsModel();
} }
public MTableModel(String tableName) { public MTableModel(String tableName) {
this.emptyResult = false;
this.success = true;
this.name = tableName; this.name = tableName;
this.column = new LinkedList<>(); this.column = new LinkedList<>();
this.rows = new MRowsModel(); this.rows = new MRowsModel();
} }
public MTableModel(String... columns) { public MTableModel(String... columns) {
this.emptyResult = false;
this.success = true;
this.name = null; this.name = null;
this.column = new LinkedList<>(); this.column = new LinkedList<>();
this.rows = new MRowsModel(); 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() { public String getName() {
return name; return name;
} }
public void setName(String name) { public void addColumn(String name) {
if (this.name != null)
this.name = name;
}
public MTableModel addColumn(String name) {
column.add(name); column.add(name);
return this;
} }
public MTableModel addRow(MRowModel row) { public void addRow(MRowModel row) {
rows.addRow(row); rows.addRow(row);
return this;
} }
public MRowsModel getRows() { public MRowsModel getRows() {
@@ -96,4 +112,7 @@ public class MTableModel {
public String toString() { public String toString() {
return "Column: " + column + ", Rows (" + getNbRows() + "): " + rows; return "Column: " + column + ", Rows (" + getNbRows() + "): " + rows;
} }
} }
@@ -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;
}
}
@@ -6,12 +6,17 @@ package netneutrality.handler;
* https://discord.gg/CdFcyQ * https://discord.gg/CdFcyQ
*/ */
import netneutrality.GuildManager;
import netneutrality.MusicBot;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandExecutionException; import netneutrality.exceptions.CommandExecutionException;
import netneutrality.utils.MessageFunction;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.sql.SQLException;
public class LogHandler { public class LogHandler {
private final static Logger logger = LoggerFactory.getLogger(LogHandler.class); private final static Logger logger = LoggerFactory.getLogger(LogHandler.class);
@@ -27,24 +32,52 @@ public class LogHandler {
sendMessageToChannel((CommandErrorException) e); sendMessageToChannel((CommandErrorException) e);
} else if (e instanceof CommandExecutionException) { } else if (e instanceof CommandExecutionException) {
logInternally((CommandExecutionException) e); logInternally((CommandExecutionException) e);
tryLogToDebugChannel((CommandExecutionException) e);
} else if (e instanceof SQLException) {
logger.error(e.getMessage(), e);
} else { } else {
logger.error(e.getMessage(), e); 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) { 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); log((Exception) e);
} }
private static void logInternally(CommandExecutionException error) { private static void logInternally(CommandExecutionException error) {
CommandContext context = error.getCommandContext(); 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) { private static void sendMessageToChannel(CommandErrorException error) {
CommandContext context = error.getCommandContext(); CommandContext context = error.getCommandContext();
logger.error("Exception thrown from command [{}] in guild [{}]: {}", context.getCommand().getCommandName(), context.getGuild().getId(), error.getMessage());
context.reply(error.getMessage()); context.reply(error.getMessage());
} }
} }
@@ -1,4 +1,4 @@
package netneutrality.handler; package netneutrality.handler.hooks.guilds;
/* /*
* Copyright (c) anthorob * 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.GuildJoinEvent;
import net.dv8tion.jda.api.events.guild.GuildLeaveEvent; import net.dv8tion.jda.api.events.guild.GuildLeaveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;
import netneutrality.db.DBController; import netneutrality.GuildManager;
import netneutrality.db.controllers.DBGuild;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class ServerJoinHandler extends ListenerAdapter { public class ServerJoinHandler extends ListenerAdapter {
@Override @Override
public void onGuildJoin(@NotNull GuildJoinEvent event) { public void onGuildJoin(@NotNull GuildJoinEvent event) {
((DBGuild) DBController.get("guild")).insertGuildInDB(event.getGuild()); GuildManager.getManager(event.getGuild()).handleJoinEvent();
} }
@Override @Override
public void onGuildLeave(@NotNull GuildLeaveEvent event) { public void onGuildLeave(@NotNull GuildLeaveEvent event) {
((DBGuild) DBController.get("guild")).removeGuildInDB(event.getGuild()); GuildManager.getManager(event.getGuild()).removeFromDB();
} }
} }
@@ -1,4 +1,4 @@
package netneutrality.handler.message; package netneutrality.handler.hooks.message;
/* /*
* Copyright (c) anthorob * Copyright (c) anthorob
@@ -1,4 +1,4 @@
package netneutrality.handler.message; package netneutrality.handler.hooks.message;
/* /*
* Copyright (c) anthorob * Copyright (c) anthorob
* *
@@ -30,11 +30,11 @@ public class MessageReceivedHandler extends ListenerAdapter {
if (user.isBot()) return; if (user.isBot()) return;
if (event.isWebhookMessage()) return; if (event.isWebhookMessage()) return;
CommandContext context = CommandContext.createContext(event);
GuildManager.getManager(guild).getRateLimiter().check(member, message, channel); GuildManager.getManager(guild).getRateLimiter().check(member, message, channel);
GuildManager.getManager(guild).checkAndLogMessage(message, member, channel); GuildManager.getManager(guild).checkAndLogMessage(message, member, channel);
CommandContext context = CommandContext.createContext(event);
String msg = message.getContentDisplay().trim(); String msg = message.getContentDisplay().trim();
if (msg.startsWith(Settings.getInstance().get("BOT_PREFIX", "$"))) { if (msg.startsWith(Settings.getInstance().get("BOT_PREFIX", "$"))) {
@@ -11,6 +11,7 @@ import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeHttpContextFilter;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
@@ -19,6 +20,8 @@ import net.dv8tion.jda.api.entities.VoiceChannel;
import netneutrality.ThreadManager; import netneutrality.ThreadManager;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandErrorException;
import netneutrality.thread.MusicPlayerAutoDisconnectThread;
import netneutrality.utils.Settings;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -34,11 +37,12 @@ public class MusicManager {
private final static Logger logger = LoggerFactory.getLogger(MusicManager.class); private final static Logger logger = LoggerFactory.getLogger(MusicManager.class);
private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager(); private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
private final static Map<String, MusicManager> managers = new ConcurrentHashMap<>();
private final Guild guild; private final Guild guild;
private final AudioPlayer player; private final AudioPlayer player;
private final TrackScheduler scheduler; private final TrackScheduler scheduler;
private final static Map<String, MusicManager> managers = new ConcurrentHashMap<>(); ScheduledExecutorService autoDisconnectThread;
private MusicManager(Guild guild) { private MusicManager(Guild guild) {
@@ -48,6 +52,8 @@ public class MusicManager {
guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player)); guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player));
player.addListener(scheduler); player.addListener(scheduler);
player.setVolume(15); 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); managers.put(guild.getId(), this);
} }
@@ -60,25 +66,22 @@ public class MusicManager {
} }
} }
public static void registerSources() { public static void initPlayerManager() {
AudioSourceManagers.registerRemoteSources(playerManager); AudioSourceManagers.registerRemoteSources(playerManager);
YoutubeHttpContextFilter.setPAPISID(Settings.getInstance().get("BOT_PAPISID", ""));
YoutubeHttpContextFilter.setPSID(Settings.getInstance().get("BOT_PSID", ""));
} }
public boolean isConnectedTo(VoiceChannel vChannel) { public boolean isConnectedTo(VoiceChannel vChannel) {
return vChannel != null && vChannel.equals(guild.getAudioManager().getConnectedChannel()); return vChannel != null && vChannel.equals(guild.getAudioManager().getConnectedChannel());
} }
public synchronized void connect(VoiceChannel vChannel) { public void connect(VoiceChannel vChannel) {
if (vChannel != null && !isConnectedTo(vChannel)) { if (vChannel != null && !isConnectedTo(vChannel)) {
guild.getAudioManager().openAudioConnection(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 { } else {
logger.error("Error connecting!"); throw new RuntimeException("Error connecting to voice channel");
} }
} }
@@ -96,6 +99,10 @@ public class MusicManager {
return info.getRequester(); return info.getRequester();
} }
public Guild getGuild() {
return guild;
}
public void leave() { public void leave() {
if (isConnected()) { if (isConnected()) {
player.stopTrack(); player.stopTrack();
@@ -103,7 +110,6 @@ public class MusicManager {
} }
scheduler.resetTopic(); scheduler.resetTopic();
System.out.println(scheduler.getQueue().size());
} }
public static void disconnectPlayers() { public static void disconnectPlayers() {
@@ -133,7 +139,6 @@ public class MusicManager {
} }
VoiceChannel vChannel = member.getVoiceState().getChannel(); VoiceChannel vChannel = member.getVoiceState().getChannel();
if (needToBeConnected && !isConnectedTo(vChannel)) { if (needToBeConnected && !isConnectedTo(vChannel)) {
throw new CommandErrorException("Not in your voice channel", context, null); throw new CommandErrorException("Not in your voice channel", context, null);
} }
@@ -168,29 +173,33 @@ public class MusicManager {
public void voteSkip(CommandContext context) { public void voteSkip(CommandContext context) {
Queue<TrackScheduler.TrackInfo> queue = scheduler.getQueue(); Queue<TrackScheduler.TrackInfo> queue = scheduler.getQueue();
VoiceChannel voiceChannel = guild.getAudioManager().getConnectedChannel(); VoiceChannel voiceChannel = guild.getAudioManager().getConnectedChannel();
TrackScheduler.TrackInfo info = queue.peek();
if (getCurrentlyPlaying() == null) { if (getCurrentlyPlaying() == null) {
return; return;
} }
if (info == null) {
return;
}
// Minus the bot itself // Minus the bot itself
int connected = voiceChannel.getMembers().size() - 1; int connected = voiceChannel.getMembers().size() - 1;
if (connected > 2) {
TrackScheduler.TrackInfo info = queue.peek();
if (connected > 2) {
double needed = connected / 2.1; double needed = connected / 2.1;
if (info != null) {
info.toggleSkip(context.getGuildUser()); info.toggleSkip(context.getGuildUser());
if (info.getSkips().size() > needed) { if (info.getSkips().size() > needed) {
context.reply("Skipping current track: %s", info.getTrack().getInfo().title);
skip(1); skip(1);
} else { } else {
context.reply(String.format("Current skips: %d/%f", info.getSkips().size(), Math.ceil(needed))); context.reply("Current skips: %d/%d", info.getSkips().size(), (int) Math.ceil(needed));
}
} }
} else { } else {
context.reply("Skipping current track since not enough people are connected to the voice channel.");
skip(1); skip(1);
} }
} }
@@ -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<Member> members = channel.getMembers().stream().filter(member -> !member.getId().equals(MusicBot.getSelf().getId())).toList();
if (members.size() == 0)
manager.leave();
}
}
}
@@ -17,10 +17,12 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.*;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.db.DBController; import netneutrality.db.DBController;
import netneutrality.db.controllers.DBBlacklist; import netneutrality.db.controllers.DBBlacklist;
import netneutrality.db.models.MBlacklist; import netneutrality.db.models.MBlacklist;
import netneutrality.exceptions.CommandExecutionException;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import org.apache.commons.lang3.time.DurationFormatUtils; import org.apache.commons.lang3.time.DurationFormatUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -179,7 +181,7 @@ public class MessageFunction {
message.setColor(Color.GREEN); 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; 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) { public static void checkBlacklist(Guild guild, Message message, TextChannel channel) {
((DBBlacklist) DBController.get("blacklist")).getBlacklistFromServer(guild.getId(), mBlacklists -> { ((DBBlacklist) DBController.get("blacklist")).getBlacklistFromServer(guild.getId(), mBlacklists -> {
@@ -211,4 +228,6 @@ public class MessageFunction {
}); });
} }
} }
@@ -67,13 +67,4 @@ public class Settings {
return get("BOT_OWNER"); return get("BOT_OWNER");
} }
public String getOwnerGuild() {
return get("BOT_OWNERGUILD");
}
public String getLogChannel() {
return get("BOT_ERRORCHANNEL");
}
} }