Add command usage to commands, add configurable base volume, improve music player to be thread-safe, rework delete queue command

This commit is contained in:
anthorob committed 2022-02-27 14:17:24 -05:00
1 parent e0767ed31a
commit 3b7d8bc6b9
43 files changed
+332 -481

No files matched your search

@@ -0,0 +1,2 @@
ALTER TABLE `guild_settings` ADD `music_volume` INT NOT NULL DEFAULT '30' AFTER `music_channel`;
+11 -18
View File
@@ -28,31 +28,24 @@ public class GuildManager {
public enum GuildSetting { public enum GuildSetting {
MUSIC_ROLE("MUSIC_ROLE", ""), MUSIC_ROLE("MUSIC_ROLE", ""),
MUSIC_CHANNEL("MUSIC_CHANNEL", ""), MUSIC_CHANNEL("MUSIC_CHANNEL", ""),
MUSIC_VOLUME("MUSIC_VOLUME", 30),
BLACKLIST_CHANNELS("BLACKLIST_EXCLUDE_CHANNELS", ""); BLACKLIST_CHANNELS("BLACKLIST_EXCLUDE_CHANNELS", "");
private final String setting; private final String name;
private final String defaultValue; private final Object defaultValue;
GuildSetting(String setting, String defaultValue) { GuildSetting(String name, Object defaultValue) {
this.setting = setting; this.name = name;
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
} }
public String getSetting() { public String getName() {
return setting; return name;
} }
public String getDefaultValue() { public Object getDefaultValue() {
return defaultValue; return defaultValue;
} }
@Override
public String toString() {
if (setting == null)
return defaultValue;
return setting;
}
} }
public static final Logger logger = LoggerFactory.getLogger(GuildManager.class); public static final Logger logger = LoggerFactory.getLogger(GuildManager.class);
@@ -87,8 +80,8 @@ public class GuildManager {
return managers.getOrDefault(guildId, null); return managers.getOrDefault(guildId, null);
} }
public String getSetting(GuildSetting key) { public Object getSetting(GuildSetting key) {
return guildEntity.getSettings().getSettingByKey(key.toString()); return guildEntity.getSettings().getSettingByKey(key);
} }
public boolean isLoggingEnabled() { public boolean isLoggingEnabled() {
@@ -99,7 +92,7 @@ public class GuildManager {
return guildEntity.isDebug(); return guildEntity.isDebug();
} }
public Map<String, String> getSettings() { public Map<String, Object> getSettings() {
return guildEntity.getSettings().getSettings(); return guildEntity.getSettings().getSettings();
} }
@@ -12,8 +12,6 @@ import net.dv8tion.jda.api.entities.Role;
import netneutrality.GuildManager; import netneutrality.GuildManager;
import netneutrality.utils.UserFunction; import netneutrality.utils.UserFunction;
import java.util.List;
public abstract class AbstractMusicCommand extends AbstractCommand { public abstract class AbstractMusicCommand extends AbstractCommand {
@Override @Override
@@ -28,7 +26,7 @@ public abstract class AbstractMusicCommand extends AbstractCommand {
@Override @Override
public boolean canBeExecutedBy(Guild guild, Member member) { public boolean canBeExecutedBy(Guild guild, Member member) {
String roleDb = GuildManager.getManager(guild).getSetting(GuildManager.GuildSetting.MUSIC_ROLE); String roleDb = (String) GuildManager.getManager(guild).getSetting(GuildManager.GuildSetting.MUSIC_ROLE);
boolean can = true; boolean can = true;
//System.out.println(roleDb); //System.out.println(roleDb);
@@ -17,7 +17,6 @@ import netneutrality.handler.LogHandler;
import netneutrality.utils.Settings; import netneutrality.utils.Settings;
import netneutrality.utils.UserFunction; import netneutrality.utils.UserFunction;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -105,10 +104,12 @@ public class CommandContext {
return command; return command;
} }
public void reply(String msg) { public void reply(CommandUsage usage) {
if (channel != null) { reply(new MessageBuilder(usage.toString()).build());
channel.sendMessage(msg).queue();
} }
public void reply(String msg) {
reply(new MessageBuilder(msg).build());
} }
public void reply(String format, Object... arguments) { public void reply(String format, Object... arguments) {
@@ -116,25 +117,25 @@ public class CommandContext {
} }
public void reply(Message msg) { public void reply(Message msg) {
if (channel != null) { if (channel != null && channel.canTalk()) {
channel.sendMessage(msg).queue(); channel.sendMessage(msg).queue();
} }
} }
public void reply(MessageEmbed embed, MessageEmbed... embeds) { public void reply(MessageEmbed embed, MessageEmbed... embeds) {
if (channel != null) { if (channel != null && channel.canTalk()) {
channel.sendMessageEmbeds(embed, embeds).queue(); channel.sendMessageEmbeds(embed, embeds).queue();
} }
} }
public void reply(Collection<? extends MessageEmbed> embeds) { public void reply(Collection<? extends MessageEmbed> embeds) {
if (channel != null) { if (channel != null && channel.canTalk()) {
channel.sendMessageEmbeds(embeds).queue(); channel.sendMessageEmbeds(embeds).queue();
} }
} }
public void replyPrivate(String msg) { public void replyPrivate(String msg) {
replyPrivate(new MessageBuilder().append(msg).build()); replyPrivate(new MessageBuilder(msg).build());
} }
public void replyPrivate(Message msg) { public void replyPrivate(Message msg) {
@@ -19,8 +19,8 @@ import java.util.Set;
public class CommandManager { public class CommandManager {
private final static Logger logger = LoggerFactory.getLogger(CommandManager.class); private final static Logger logger = LoggerFactory.getLogger(CommandManager.class);
public static HashMap<String, AbstractCommand> commands = new HashMap<>(); public static final HashMap<String, AbstractCommand> commands = new HashMap<>();
public static HashMap<String, AbstractCommand> commandsAlias = new HashMap<>(); public static final HashMap<String, AbstractCommand> commandsAlias = new HashMap<>();
public static void init() { public static void init() {
initCommands(); initCommands();
@@ -1,4 +1,5 @@
package netneutrality.command;/* package netneutrality.command;
/*
* Copyright (c) anthorob * Copyright (c) anthorob
* *
* https://xtremcommunity.com/ * https://xtremcommunity.com/
@@ -46,9 +47,11 @@ public class CommandUsage {
} }
} }
private final AbstractCommand command;
private final Set<Argument> args = new HashSet<>(); private final Set<Argument> args = new HashSet<>();
public CommandUsage(Argument... arguments) { public CommandUsage(AbstractCommand command, Argument... arguments) {
this.command = command;
Collections.addAll(args, arguments); Collections.addAll(args, arguments);
} }
@@ -57,19 +60,33 @@ public class CommandUsage {
return this; return this;
} }
public static CommandUsage create(Argument... arguments) { public static CommandUsage create(AbstractCommand command, Argument... arguments) {
return new CommandUsage(arguments); return new CommandUsage(command, arguments);
} }
public AbstractCommand getCommand() {
return command;
}
public int getRequiredArguments() {
return args.size();
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Available arguments: ").append(args.size()).append("\n"); sb.append("Available arguments: ").append(args.size()).append("\n");
sb.append(command.getCommandName()).append(" ");
for (Argument arg : args) { for (Argument arg : args) {
sb.append("<"); sb.append("<");
if (arg.getType() == Argument.Type.OPTIONAL) if (arg.getType() == Argument.Type.OPTIONAL) {
sb.append("Optional argument: ").append(arg.getDescription()); sb.append("optional: ");
if (arg.getValues() != null || arg.getValues().length != 0)
sb.append(Arrays.toString(arg.getValues())).append(": ");
sb.append(arg.getDescription());
}
if (arg.getType() == Argument.Type.REQUIRED) { if (arg.getType() == Argument.Type.REQUIRED) {
sb.append("required: ").append(Arrays.toString(arg.getValues())); sb.append("required: ").append(Arrays.toString(arg.getValues()));
@@ -1,4 +1,5 @@
package netneutrality.command;/* package netneutrality.command;
/*
* Copyright (c) anthorob * Copyright (c) anthorob
* *
* https://xtremcommunity.com/ * https://xtremcommunity.com/
@@ -34,7 +35,7 @@ public interface ICommand {
*/ */
String[] getAlias(); String[] getAlias();
String getUsage(); CommandUsage getUsage();
String getDescription(); String getDescription();
@@ -37,8 +37,10 @@ public class HelpCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return CommandUsage.create(this,
new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"command"}, "Name of command to get help with")
);
} }
@Override @Override
@@ -70,7 +72,7 @@ public class HelpCommand extends AbstractCommand {
context.replyPrivate("Command [" + c.getCommandName() + "] requires admin privileges"); context.replyPrivate("Command [" + c.getCommandName() + "] requires admin privileges");
} }
System.out.println(CommandUsage.create(new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"get", "add"}, ""))); System.out.println(CommandUsage.create(c, new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"get", "add"}, "")));
MessageEmbed help = MessageFunction.buildHelpMessage(c); MessageEmbed help = MessageFunction.buildHelpMessage(c);
context.reply(new MessageBuilder().append(context.getDiscordUser()).append(" help has been sent your way!").build()); context.reply(new MessageBuilder().append(context.getDiscordUser()).append(" help has been sent your way!").build());
@@ -6,10 +6,10 @@ package netneutrality.command.basic;
* https://discord.gg/CdFcyQ * https://discord.gg/CdFcyQ
*/ */
import netneutrality.MusicBot;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
public class PingCommand extends AbstractCommand { public class PingCommand extends AbstractCommand {
@@ -34,7 +34,7 @@ public class PingCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -11,8 +11,11 @@ import netneutrality.GuildManager;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
import netneutrality.db.DBController; import netneutrality.db.DBController;
import netneutrality.db.MysqlDatabase; import netneutrality.db.MysqlDatabase;
import netneutrality.exceptions.CommandErrorException;
import netneutrality.music.MusicManager;
import java.util.List; import java.util.List;
@@ -38,8 +41,10 @@ public class ConfigureCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return CommandUsage.create(this,
new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"musicrole", "musicvolume"}, "")
);
} }
@Override @Override
@@ -63,7 +68,7 @@ public class ConfigureCommand extends AbstractCommand {
if (context.getArg(0).equals("musicrole")) { if (context.getArg(0).equals("musicrole")) {
if (args.length == 1) { if (args.length == 1) {
String roleDb = guildManager.getSetting(GuildManager.GuildSetting.MUSIC_ROLE); String roleDb = (String) guildManager.getSetting(GuildManager.GuildSetting.MUSIC_ROLE);
Role role = null; Role role = null;
if (!roleDb.isEmpty()) { if (!roleDb.isEmpty()) {
role = context.getGuild().getRoleById(roleDb); role = context.getGuild().getRoleById(roleDb);
@@ -92,7 +97,30 @@ public class ConfigureCommand extends AbstractCommand {
} }
} }
if (context.getArg(0).equals("musicvolume")) {
if (args.length == 1) {
int volume = (int) guildManager.getSetting(GuildManager.GuildSetting.MUSIC_VOLUME);
context.reply("Default volume for music player: " + volume);
}
if (args.length == 2) {
try {
int volume = Integer.parseInt(args[1]);
database.prepareAndExecuteAsync("UPDATE guild_settings SET music_volume = ? WHERE guild_id = ?", volume, context.getGuild().getId()).blocking();
guildManager.reloadSettings();
MusicManager.get(context.getGuild()).setVolume(volume);
context.reply("Default volume for music player is now %d", volume);
} catch (NumberFormatException e) {
throw new CommandErrorException("Not a value between 0 and 100", context, e);
}
}
}
} else {
context.reply(getUsage());
} }
} }
} }
@@ -9,6 +9,7 @@ package netneutrality.command.crypto;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandExecutionException; import netneutrality.exceptions.CommandExecutionException;
import netneutrality.http.WebModule; import netneutrality.http.WebModule;
@@ -44,8 +45,10 @@ public class BitcoinPriceCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return CommandUsage.create(this,
new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"currency"}, "defaults to USD")
);
} }
@Override @Override
@@ -74,7 +77,7 @@ public class BitcoinPriceCommand extends AbstractCommand {
String finalCurrency = currency; String finalCurrency = currency;
context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> { context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> {
String price = "0"; String price;
Locale usa = new Locale("en", "US"); Locale usa = new Locale("en", "US");
NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa); NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
dollarFormat.setMaximumFractionDigits(24); dollarFormat.setMaximumFractionDigits(24);
@@ -9,6 +9,7 @@ package netneutrality.command.crypto;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandExecutionException; import netneutrality.exceptions.CommandExecutionException;
import netneutrality.http.WebModule; import netneutrality.http.WebModule;
@@ -43,8 +44,11 @@ public class CryptoPriceCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return "<crypto> <currency (optional)>"; return CommandUsage.create(this,
new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"crypto"}, "Symbol of crypto"),
new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"currency"}, "defaults to USD")
);
} }
@Override @Override
@@ -76,7 +80,7 @@ public class CryptoPriceCommand extends AbstractCommand {
String crypto = args[0].toUpperCase(); String crypto = args[0].toUpperCase();
String finalCurrency = currency; String finalCurrency = currency;
context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> { context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> {
String price = "0"; String price;
Locale usa = new Locale("en", "US"); Locale usa = new Locale("en", "US");
NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa); NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
dollarFormat.setMaximumFractionDigits(24); dollarFormat.setMaximumFractionDigits(24);
@@ -9,6 +9,7 @@ package netneutrality.command.crypto;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandExecutionException; import netneutrality.exceptions.CommandExecutionException;
import netneutrality.http.WebModule; import netneutrality.http.WebModule;
@@ -44,8 +45,10 @@ public class EthereumPriceCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return CommandUsage.create(this,
new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"currency"}, "defaults to USD")
);
} }
@Override @Override
@@ -74,7 +77,7 @@ public class EthereumPriceCommand extends AbstractCommand {
String finalCurrency = currency; String finalCurrency = currency;
context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> { context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> {
String price = "0"; String price;
Locale usa = new Locale("en", "US"); Locale usa = new Locale("en", "US");
NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa); NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
dollarFormat.setMaximumFractionDigits(24); dollarFormat.setMaximumFractionDigits(24);
@@ -9,6 +9,7 @@ package netneutrality.command.crypto;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandExecutionException; import netneutrality.exceptions.CommandExecutionException;
import netneutrality.http.WebModule; import netneutrality.http.WebModule;
@@ -44,8 +45,10 @@ public class LitecoinPriceCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return CommandUsage.create(this,
new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"currency"}, "defaults to USD")
);
} }
@Override @Override
@@ -74,7 +77,7 @@ public class LitecoinPriceCommand extends AbstractCommand {
String finalCurrency = currency; String finalCurrency = currency;
context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> { context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> {
String price = "0"; String price;
Locale usa = new Locale("en", "US"); Locale usa = new Locale("en", "US");
NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa); NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
dollarFormat.setMaximumFractionDigits(24); dollarFormat.setMaximumFractionDigits(24);
@@ -0,0 +1 @@
*.java
@@ -9,6 +9,7 @@ package netneutrality.command.message;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
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;
@@ -39,7 +40,7 @@ public class BlacklistCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -94,9 +95,9 @@ public class BlacklistCommand extends AbstractCommand {
case "remove": case "remove":
if (controller.delete(word, context.getGuild().getId())) { if (controller.delete(word, context.getGuild().getId())) {
context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); context.reply("Removed the word \"" + word + "\" from the blacklist.");
} else { } else {
context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); context.reply("Error removing \"" + word + "\" from the blacklist");
} }
break; break;
@@ -104,9 +105,9 @@ public class BlacklistCommand extends AbstractCommand {
case "disable": case "disable":
if (controller.disable(word, context.getGuild().getId())) { if (controller.disable(word, context.getGuild().getId())) {
context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); context.reply("Removed the word \"" + word + "\" from the blacklist.");
} else { } else {
context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); context.reply("Error removing \"" + word + "\" from the blacklist");
} }
break; break;
@@ -114,9 +115,9 @@ public class BlacklistCommand extends AbstractCommand {
case "enable": case "enable":
if (controller.enable(word, context.getGuild().getId())) { if (controller.enable(word, context.getGuild().getId())) {
context.getChannel().sendMessage("Removed the word \"" + word + "\" from the blacklist.").queue(); context.reply("Removed the word \"" + word + "\" from the blacklist.");
} else { } else {
context.getChannel().sendMessage("Error removing \"" + word + "\" from the blacklist").queue(); context.reply("Error removing \"" + word + "\" from the blacklist");
} }
break; break;
@@ -9,6 +9,7 @@ package netneutrality.command.message;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
import netneutrality.utils.ChannelFunction; import netneutrality.utils.ChannelFunction;
public class PruneCommand extends AbstractCommand { public class PruneCommand extends AbstractCommand {
@@ -34,8 +35,10 @@ public class PruneCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return "<number of messages to delete (max 2499)>"; return CommandUsage.create(this,
new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"number"}, "Max 2499")
);
} }
@Override @Override
@@ -10,6 +10,7 @@ package netneutrality.command.music;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
public class BitconnectCommand extends AbstractMusicCommand { public class BitconnectCommand extends AbstractMusicCommand {
@@ -30,7 +31,7 @@ public class BitconnectCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -10,6 +10,7 @@ package netneutrality.command.music;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandUsage;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MessageFunction; import netneutrality.utils.MessageFunction;
import netneutrality.utils.MusicUtils; import netneutrality.utils.MusicUtils;
@@ -32,7 +33,7 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -48,9 +49,9 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand {
MusicUtils.checkIfConnected(player, context); MusicUtils.checkIfConnected(player, context);
if (player.getCurrentlyPlaying() != null) { if (player.getCurrentlyPlaying() != null) {
context.getChannel().sendMessageEmbeds(MessageFunction.buildCurrentlyPlayingMessage(player, member)).queue(); context.reply(MessageFunction.buildCurrentlyPlayingMessage(player, member));
} else { } else {
context.getChannel().sendMessage("Player is not playing any tracks right now").queue(); context.reply("Player is not playing any tracks right now");
} }
} }
@@ -9,7 +9,10 @@ package netneutrality.command.music;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandUsage;
import netneutrality.exceptions.CommandErrorException;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MessageFunction;
import netneutrality.utils.MusicUtils; import netneutrality.utils.MusicUtils;
public class DeleteQueueCommand extends AbstractMusicCommand { public class DeleteQueueCommand extends AbstractMusicCommand {
@@ -30,17 +33,19 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
@Override @Override
public String[] getAlias() { public String[] getAlias() {
return new String[]{"delq"}; return new String[] {"delq", "delqueue"};
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return CommandUsage.create(this,
new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"track #", "all"}, "")
);
} }
@Override @Override
public String getDescription() { public String getDescription() {
return "Deletes the music queue"; return "Empties the music queue";
} }
@Override @Override
@@ -48,13 +53,44 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
MusicManager player = MusicManager.get(context.getGuild()); MusicManager player = MusicManager.get(context.getGuild());
MusicUtils.checkIfConnected(player, context); MusicUtils.checkIfConnected(player, context);
int queueSize = player.getScheduler().getQueue().size(); if (context.getArgumentsAsArray().length == 0) {
if (queueSize > 0) { context.reply("Select the track you want to delete from the queue (track# or all)");
player.getScheduler().getQueue().clear(); context.reply(MessageFunction.buildViewQueueMessage(player, context.getGuildUser(), true));
context.getChannel().sendMessage("Removed " + queueSize + (queueSize > 1 ? " tracks" : "track") + " from the queue").queue();
} else {
context.getChannel().sendMessage("Queue is empty!").queue();
} }
if (context.getArgumentsAsArray().length > 0) {
int queueSize = player.getScheduler().getQueue().size();
if (context.getArg(0).equals("all")) {
if (queueSize > 0) {
player.leave();
player.getScheduler().getQueue().clear();
context.reply("Removed " + queueSize-- + (queueSize > 1 ? " tracks" : "track") + " from the queue");
} else {
context.reply("Queue is empty!");
}
} else {
try {
int num = Integer.parseInt(context.getArg(0));
if (num > 0) {
player.removeFromQueue(num);
context.reply("Removing track #%d from the queue", num);
} else {
context.reply("Number out of range");
}
} catch (NumberFormatException e) {
throw new CommandErrorException("Please enter a number", context, e);
}
}
}
} }
} }
@@ -10,10 +10,10 @@ 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.command.CommandUsage;
import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandExecutionException; import netneutrality.exceptions.CommandExecutionException;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils;
public class JoinCommand extends AbstractMusicCommand { public class JoinCommand extends AbstractMusicCommand {
@@ -33,7 +33,7 @@ public class JoinCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -9,6 +9,7 @@ package netneutrality.command.music;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandUsage;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils; import netneutrality.utils.MusicUtils;
@@ -34,7 +35,7 @@ public class LeaveCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -9,6 +9,7 @@ package netneutrality.command.music;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandUsage;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
public class PlayCommand extends AbstractMusicCommand { public class PlayCommand extends AbstractMusicCommand {
@@ -29,8 +30,11 @@ public class PlayCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return "<url>"; return CommandUsage.create(
this,
new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"url"}, "Youtube/Soundcloud link or search string")
);
} }
@Override @Override
@@ -47,7 +51,7 @@ public class PlayCommand extends AbstractMusicCommand {
player.play(context.getMessageText(), context, false, false); player.play(context.getMessageText(), context, false, false);
} else { } else {
context.reply("No url provided"); context.reply(getUsage());
} }
} }
@@ -9,6 +9,7 @@ package netneutrality.command.music;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandUsage;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils; import netneutrality.utils.MusicUtils;
import netneutrality.utils.UserFunction; import netneutrality.utils.UserFunction;
@@ -30,8 +31,8 @@ public class SkipCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return "<number of track to skip (optional)>"; return CommandUsage.create(this, new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[]{"number"}, "Number of tracks to skip"));
} }
@Override @Override
@@ -45,6 +46,7 @@ public class SkipCommand extends AbstractMusicCommand {
MusicUtils.checkIfConnected(player, context); MusicUtils.checkIfConnected(player, context);
// Combined fonctionality of vote skip // Combined fonctionality of vote skip
//TODO: clean ifs
if (context.getArgumentsAsArray().length > 0 && UserFunction.isAdmin(context.getGuildUser())) { if (context.getArgumentsAsArray().length > 0 && UserFunction.isAdmin(context.getGuildUser())) {
int skips = Integer.parseInt(context.getArg(0)); int skips = Integer.parseInt(context.getArg(0));
player.skip(skips); player.skip(skips);
@@ -9,6 +9,7 @@ package netneutrality.command.music;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandUsage;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils; import netneutrality.utils.MusicUtils;
import netneutrality.utils.UserFunction; import netneutrality.utils.UserFunction;
@@ -31,13 +32,13 @@ public class StopCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@Override @Override
public String getDescription() { public String getDescription() {
return "Stop the music player, deleting the queue in the process"; return "Stop the music player, emptying the queue in the process";
} }
@Override @Override
@@ -45,12 +46,7 @@ public class StopCommand extends AbstractMusicCommand {
MusicManager player = MusicManager.get(context.getGuild()); MusicManager player = MusicManager.get(context.getGuild());
MusicUtils.checkIfConnected(player, context); MusicUtils.checkIfConnected(player, context);
if (UserFunction.isAdmin(context.getGuildUser())) { if (UserFunction.isAdmin(context.getGuildUser()) || context.getGuildUser().getId().equals(player.getRequesterOfCurrentTrack().getId())) {
player.leave();
return;
}
if (context.getGuildUser().getId().equals(player.getRequesterOfCurrentTrack().getId())) {
player.leave(); player.leave();
} }
} }
@@ -10,6 +10,7 @@ package netneutrality.command.music;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandUsage;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MessageFunction; import netneutrality.utils.MessageFunction;
import netneutrality.utils.MusicUtils; import netneutrality.utils.MusicUtils;
@@ -36,7 +37,7 @@ public class ViewQueueCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -53,7 +54,7 @@ public class ViewQueueCommand extends AbstractMusicCommand {
int queueSize = player.getScheduler().getQueue().size(); int queueSize = player.getScheduler().getQueue().size();
if (queueSize > 0) { if (queueSize > 0) {
context.reply(MessageFunction.buildViewQueueMessage(player, member)); context.reply(MessageFunction.buildViewQueueMessage(player, member, true));
} else { } else {
context.reply("Queue is empty!"); context.reply("Queue is empty!");
} }
@@ -36,8 +36,8 @@ public class VolumeCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return "<integer between 0 and 100 (optional)>"; return CommandUsage.create(this, new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"0-100"}, ""));
} }
@Override @Override
@@ -53,6 +53,7 @@ public class VolumeCommand extends AbstractMusicCommand {
try { try {
int volume = Integer.parseInt(context.getArgumentsAsArray()[0]); int volume = Integer.parseInt(context.getArgumentsAsArray()[0]);
player.setVolume(volume); player.setVolume(volume);
context.reply("Volume set to %s", volume);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new CommandErrorException("Please enter a value from 0 to 100", context, null); throw new CommandErrorException("Please enter a value from 0 to 100", context, null);
} }
@@ -8,6 +8,7 @@ package netneutrality.command.music;
import netneutrality.command.AbstractMusicCommand; import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandUsage;
import netneutrality.music.MusicManager; import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils; import netneutrality.utils.MusicUtils;
@@ -29,7 +30,7 @@ public class VoteSkipCommand extends AbstractMusicCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -11,6 +11,7 @@ import net.dv8tion.jda.api.entities.User;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
import netneutrality.db.DBController; import netneutrality.db.DBController;
import netneutrality.db.controllers.DBMessage; import netneutrality.db.controllers.DBMessage;
import netneutrality.db.models.MMessage; import netneutrality.db.models.MMessage;
@@ -44,7 +45,7 @@ public class DatabaseCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -84,7 +85,7 @@ public class DatabaseCommand extends AbstractCommand {
embed.setDescription( embed.setDescription(
"Message from " + message.getSender() + " on the channel " + message.getChannelName()); "Message from " + message.getSender() + " on the channel " + message.getChannelName());
embed.addField("Message: ", "" + message.getMessage(), false); embed.addField("Message: ", "" + message.getMessage(), false);
context.getChannel().sendMessageEmbeds(embed.build()).queue(); context.reply(embed.build());
} else { } else {
//TODO: cached user lol xd //TODO: cached user lol xd
User user = context.getJDA().getUserById(args[1]); User user = context.getJDA().getUserById(args[1]);
@@ -102,7 +103,7 @@ public class DatabaseCommand extends AbstractCommand {
} }
embed.setFooter("Guild : " + context.getGuild().getName(), null); embed.setFooter("Guild : " + context.getGuild().getName(), null);
context.getDiscordUser().openPrivateChannel().queue(t -> t.sendMessageEmbeds(embed.build()).queue()); context.replyPrivate(embed.build());
} }
} }
@@ -1,87 +0,0 @@
package netneutrality.command.specific;
/*
* Copyright (c) anthorob
*
* https://xtremcommunity.com/
* https://discord.gg/CdFcyQ
*/
import net.dv8tion.jda.api.MessageBuilder;
import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext;
import netneutrality.command.CommandType;
import netneutrality.music.MusicManager;
import netneutrality.utils.Settings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class EvalMethod extends AbstractCommand {
@Override
public boolean needAdmin() {
return true;
}
@Override
public boolean isEnabled() {
return false;
}
@Override
public String getCommandName() {
return "evaluate";
}
@Override
public String[] getAlias() {
return new String[]{"eval"};
}
@Override
public String getUsage() {
return null;
}
@Override
public String getDescription() {
return null;
}
@Override
public CommandType getType() {
return CommandType.UNLISTED;
}
@Override
public void execute(CommandContext context) {
if (context.getDiscordUser().getId().equals(Settings.getInstance().getCreatorId())) {
ScriptEngine se = new ScriptEngineManager().getEngineByName("Nashorn");
MessageBuilder message = new MessageBuilder();
try {
se.eval("var imports = new JavaImporter(java.io, java.lang, java.util);");
se.put("jda", context.getJDA());
se.put("guild", context.getGuild());
se.put("channel", context.getChannel());
se.put("member", context.getGuildUser());
se.put("music", MusicManager.get(context.getGuild()));
String script = String.format("( function() { with (imports) { return %s } } )();", context.getMessageText());
message.append("Evaluated Successfully:");
message.appendCodeBlock(se.eval(script).toString(), "java");
context.getChannel().sendMessage(message.build()).queue();
} catch (ScriptException e) {
e.printStackTrace();
context.getChannel().sendMessage(" An exception was thrown:\n```\n" + e.getMessage() + " ```").queue();
}
}
}
}
@@ -9,6 +9,7 @@ package netneutrality.command.specific;
import netneutrality.command.AbstractCommand; import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.command.CommandType; import netneutrality.command.CommandType;
import netneutrality.command.CommandUsage;
public class LoggingCommand extends AbstractCommand { public class LoggingCommand extends AbstractCommand {
@@ -33,7 +34,7 @@ public class LoggingCommand extends AbstractCommand {
} }
@Override @Override
public String getUsage() { public CommandUsage getUsage() {
return null; return null;
} }
@@ -1,86 +0,0 @@
package netneutrality.command.specific;
/*
* Copyright (c) anthorob
*
* https://xtremcommunity.com/
* https://discord.gg/CdFcyQ
*/
import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext;
import netneutrality.command.CommandType;
import netneutrality.db.DBController;
import netneutrality.db.controllers.DBSettings;
import netneutrality.db.models.MSellyOrder;
import netneutrality.http.Selly;
import java.util.Map;
public class SellyCommand extends AbstractCommand {
@Override
public boolean needAdmin() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public String getCommandName() {
return "selly";
}
@Override
public String[] getAlias() {
return new String[0];
}
@Override
public String getUsage() {
return null;
}
@Override
public String getDescription() {
return null;
}
@Override
public CommandType getType() {
return CommandType.UNLISTED;
}
@Override
public void execute(CommandContext context) {
//TODO: delete or move to custom command when implemented
String sellyEmail = ((DBSettings) DBController.get("settings")).getSettingsByKey("selly_email");
String sellyKey = ((DBSettings) DBController.get("settings")).getSettingsByKey("");
Selly selly = new Selly(sellyEmail, sellyKey);
Map<String, MSellyOrder> orders = selly.getOrders();
System.out.println(selly.getProducts().toString());
if (context.getArgumentsAsArray().length > 1) {
String email = context.getArgumentsAsArray()[0];
String id = context.getArgumentsAsArray()[1];
if (orders.containsKey(id)) {
MSellyOrder order = orders.get(id);
if (email.equals(order.getEmail())) {
if (order.getStatus() == 100) {
context.getDiscordUser().openPrivateChannel().queue(t -> t.sendMessage("success").queue());
} else
context.getDiscordUser().openPrivateChannel().queue(t -> t.sendMessage("not completed").queue());
} else
context.getDiscordUser().openPrivateChannel().queue(t -> t.sendMessage("wrong email").queue());
} else
context.getDiscordUser().openPrivateChannel().queue(t -> t.sendMessage("order doesn't exist").queue());
} else
context.getDiscordUser().openPrivateChannel().queue(t -> t.sendMessage("usage : $selly <email> <order_id>").queue());
}
}
@@ -1,55 +0,0 @@
package netneutrality.command.specific;
/*
* Copyright (c) anthorob
*
* https://xtremcommunity.com/
* https://discord.gg/CdFcyQ
*/
import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandContext;
import netneutrality.command.CommandType;
public class TestCommand extends AbstractCommand {
@Override
public boolean needAdmin() {
return true;
}
@Override
public boolean isEnabled() {
return false;
}
@Override
public String getCommandName() {
return "test";
}
@Override
public String[] getAlias() {
return new String[0];
}
@Override
public String getUsage() {
return null;
}
@Override
public String getDescription() {
return null;
}
@Override
public CommandType getType() {
return CommandType.UNLISTED;
}
@Override
public void execute(CommandContext context) {
}
}
@@ -1,28 +0,0 @@
package netneutrality.db.controllers;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import netneutrality.db.AbstractController;
import netneutrality.db.models.MTableModel;
public class DBSettings extends AbstractController {
@Deprecated
public String getSettingsByKey(String key) {
MTableModel table = database.prepareAndExecuteAsync("SELECT value FROM settings WHERE skey = ?", key).blocking();
if (table.getNbRows() == 1) {
return table.getRow(0).get(0).toString();
}
return null;
}
@Override
public String getControllerName() {
return "settings";
}
}
@@ -5,6 +5,7 @@ package netneutrality.db.entities;/*
* https://discord.gg/CdFcyQ * https://discord.gg/CdFcyQ
*/ */
import netneutrality.GuildManager;
import netneutrality.db.models.MRowModel; import netneutrality.db.models.MRowModel;
import netneutrality.db.models.MTableModel; import netneutrality.db.models.MTableModel;
@@ -12,7 +13,7 @@ import java.util.*;
public class OGuildSetting extends AbstractEntity { public class OGuildSetting extends AbstractEntity {
private final OGuild guild; private final OGuild guild;
private Map<String, String> settings; private Map<String, Object> settings;
public OGuildSetting(OGuild OGuild) { public OGuildSetting(OGuild OGuild) {
super(OGuild.getGuildID()); super(OGuild.getGuildID());
@@ -24,16 +25,16 @@ public class OGuildSetting extends AbstractEntity {
return guild; return guild;
} }
public Map<String, String> getSettings() { public Map<String, Object> getSettings() {
return settings; return settings;
} }
public String getSettingByKey(String key) { public Object getSettingByKey(GuildManager.GuildSetting key) {
if (settings.containsKey(key)) { if (settings.containsKey(key.getName())) {
return settings.get(key); return settings.get(key.getName());
} }
return null; return key.getDefaultValue();
} }
@Override @Override
@@ -62,7 +63,7 @@ public class OGuildSetting extends AbstractEntity {
if (i == 0) continue; if (i == 0) continue;
String key = columns.get(i).toUpperCase(); String key = columns.get(i).toUpperCase();
String value = (row.getItem(i) == null ? "" : row.getItem(i).toString()); Object value = row.getItem(i);
settings.put(key, value); settings.put(key, value);
} }
@@ -1,13 +1,20 @@
package netneutrality.db.models; package netneutrality.db.models;
/*
* Copyright (c) anthorob
*
* https://xtremcommunity.com/
* https://discord.gg/CdFcyQ
*/
import java.util.List; import java.util.List;
public class MBlacklist { public class MBlacklist {
protected String word = ""; private final String word;
protected boolean enabled = false; private final boolean enabled;
protected String creatorId= ""; private final String creatorId;
protected String serverId; private final String serverId;
public MBlacklist(String word, boolean enabled, String creatorId, String serverId) { public MBlacklist(String word, boolean enabled, String creatorId, String serverId) {
this.word = word; this.word = word;
@@ -30,34 +37,18 @@ public class MBlacklist {
return word; return word;
} }
public void setWord(String word) {
this.word = word;
}
public boolean isEnabled() { public boolean isEnabled() {
return enabled; return enabled;
} }
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getCreatorId() { public String getCreatorId() {
return creatorId; return creatorId;
} }
public void setCreatorId(String creatorId) {
this.creatorId = creatorId;
}
public String getServerId() { public String getServerId() {
return serverId; return serverId;
} }
public void setServerId(String serverId) {
this.serverId = serverId;
}
@Override @Override
public String toString() { public String toString() {
return "[word=" + word + ", enabled=" + enabled + "]"; return "[word=" + word + ", enabled=" + enabled + "]";
@@ -48,7 +48,7 @@ public class ActionHandler extends AbstractHandler {
GuildManager manager = GuildManager.getManager(MusicBot.getJDA().getGuildById(guild)); GuildManager manager = GuildManager.getManager(MusicBot.getJDA().getGuildById(guild));
if (manager != null) { if (manager != null) {
Map<String, String> settings = manager.getSettings(); Map<String, Object> settings = manager.getSettings();
JSONObject setting = new JSONObject(settings); JSONObject setting = new JSONObject(settings);
json.put("status", "ok"); json.put("status", "ok");
@@ -20,6 +20,7 @@ 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.TextChannel; import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.entities.VoiceChannel;
import netneutrality.GuildManager;
import netneutrality.ThreadManager; import netneutrality.ThreadManager;
import netneutrality.command.CommandContext; import netneutrality.command.CommandContext;
import netneutrality.exceptions.CommandErrorException; import netneutrality.exceptions.CommandErrorException;
@@ -36,29 +37,31 @@ import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class MusicManager { 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 Map<String, MusicManager> managers = new ConcurrentHashMap<>(); private final static Map<String, MusicManager> managers = new ConcurrentHashMap<>();
private final static ScheduledExecutorService executor = (ScheduledExecutorService) ThreadManager.getExecutor("music", ThreadManager.ExecutorType.SCHEDULED);
private final Guild guild; private final Guild guild;
private final AudioPlayer player; private final AudioPlayer player;
private final AudioPlayerManager playerManager;
private final TrackScheduler scheduler; private final TrackScheduler scheduler;
ScheduledExecutorService autoDisconnectThread; private ScheduledFuture<?> autoDisconnectThread;
private MusicManager(Guild guild) { private MusicManager(Guild guild) {
this.guild = guild; this.guild = guild;
this.playerManager = new DefaultAudioPlayerManager();
this.player = playerManager.createPlayer(); this.player = playerManager.createPlayer();
this.scheduler = new TrackScheduler(player); this.scheduler = new TrackScheduler(player);
AudioSourceManagers.registerRemoteSources(playerManager);
guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player)); guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player));
player.addListener(scheduler); player.addListener(scheduler);
player.setVolume(15); player.setVolume((Integer) GuildManager.getManager(guild).getSetting(GuildManager.GuildSetting.MUSIC_VOLUME));
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);
} }
@@ -72,8 +75,6 @@ public class MusicManager {
} }
public static void initPlayerManager() { public static void initPlayerManager() {
AudioSourceManagers.registerRemoteSources(playerManager);
YoutubeHttpContextFilter.setPAPISID(Settings.getInstance().get("BOT_PAPISID", "")); YoutubeHttpContextFilter.setPAPISID(Settings.getInstance().get("BOT_PAPISID", ""));
YoutubeHttpContextFilter.setPSID(Settings.getInstance().get("BOT_PSID", "")); YoutubeHttpContextFilter.setPSID(Settings.getInstance().get("BOT_PSID", ""));
} }
@@ -82,9 +83,13 @@ public class MusicManager {
return vChannel != null && vChannel.equals(guild.getAudioManager().getConnectedChannel()); return vChannel != null && vChannel.equals(guild.getAudioManager().getConnectedChannel());
} }
public void connect(VoiceChannel vChannel) { public synchronized void connect(VoiceChannel vChannel) {
if (vChannel != null && !isConnectedTo(vChannel)) { if (vChannel != null && !isConnectedTo(vChannel)) {
guild.getAudioManager().openAudioConnection(vChannel); guild.getAudioManager().openAudioConnection(vChannel);
guild.getAudioManager().setSelfDeafened(true);
if (autoDisconnectThread == null)
autoDisconnectThread = executor.scheduleWithFixedDelay(new MusicPlayerAutoDisconnectThread(this), 120, 120, TimeUnit.SECONDS);
} else { } else {
throw new RuntimeException("Error connecting to voice channel"); throw new RuntimeException("Error connecting to voice channel");
} }
@@ -95,11 +100,11 @@ public class MusicManager {
return guild != null && guild.getAudioManager().getConnectedChannel() != null; return guild != null && guild.getAudioManager().getConnectedChannel() != null;
} }
public AudioTrack getCurrentlyPlaying() { public synchronized AudioTrack getCurrentlyPlaying() {
return player.getPlayingTrack(); return player.getPlayingTrack();
} }
public Member getRequesterOfCurrentTrack() { public synchronized Member getRequesterOfCurrentTrack() {
TrackScheduler.TrackInfo info = scheduler.getQueue().peek(); TrackScheduler.TrackInfo info = scheduler.getQueue().peek();
if (info == null) if (info == null)
@@ -112,13 +117,20 @@ public class MusicManager {
return guild; return guild;
} }
public void leave() { public synchronized void leave() {
if (isConnected()) { if (isConnected()) {
player.stopTrack(); player.stopTrack();
guild.getAudioManager().closeAudioConnection(); guild.getAudioManager().closeAudioConnection();
} }
scheduler.resetTopic(); scheduler.resetTopic();
if (autoDisconnectThread != null) {
boolean cancel = autoDisconnectThread.cancel(true);
if (cancel)
autoDisconnectThread = null;
}
} }
public static void disconnectPlayers() { public static void disconnectPlayers() {
@@ -135,7 +147,7 @@ public class MusicManager {
return false; return false;
} }
public void play(String url, CommandContext context, boolean needToBeConnected, boolean silent) { public synchronized void play(String url, CommandContext context, boolean needToBeConnected, boolean silent) {
Member member = context.getGuildUser(); Member member = context.getGuildUser();
TextChannel channel = context.getChannel(); TextChannel channel = context.getChannel();
@@ -160,11 +172,12 @@ public class MusicManager {
scheduler.setTextChannel(channel); scheduler.setTextChannel(channel);
if (identifier != null) { if (identifier != null) {
playerManager.loadItem(identifier, new AudioLoadResultHandler() {
playerManager.loadItemOrdered(this, identifier, new AudioLoadResultHandler() {
@Override @Override
public void trackLoaded(AudioTrack audioTrack) { public void trackLoaded(AudioTrack audioTrack) {
logger.debug("Starting track on guild {}: {}", guild.getId(), identifier); logger.debug("Found results for identifier: {}", identifier);
if (!silent) { if (!silent) {
channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(audioTrack, member, identifier)).queue(); channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(audioTrack, member, identifier)).queue();
@@ -177,22 +190,25 @@ public class MusicManager {
public void playlistLoaded(AudioPlaylist audioPlaylist) { public void playlistLoaded(AudioPlaylist audioPlaylist) {
if (identifier.startsWith("ytsearch:")) { if (identifier.startsWith("ytsearch:")) {
AudioTrack track = audioPlaylist.getTracks().get(0); AudioTrack track = audioPlaylist.getTracks().get(0);
logger.debug("Starting track on guild {}: {}", guild.getId(), identifier); logger.debug("Found results for identifier: {}", identifier);
if (!silent) if (!silent)
channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(track, member, String.format("https://youtu.be/%s", track.getIdentifier()))).queue(); channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(track, member, String.format("https://youtu.be/%s", track.getIdentifier()))).queue();
scheduler.queue(track, member); scheduler.queue(track, member);
} else { } else {
logger.debug("Starting playlist on guild {}: {}", guild.getId(), identifier); logger.debug("Found results for playlist identifier: {}", identifier);
if (!silent) if (!silent)
channel.sendMessageEmbeds(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, member, identifier)).queue(); channel.sendMessageEmbeds(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, member, identifier)).queue();
for (AudioTrack track : audioPlaylist.getTracks()) { for (AudioTrack track : audioPlaylist.getTracks()) {
synchronized (scheduler.getQueue()) {
scheduler.queue(track, member); scheduler.queue(track, member);
} }
} }
} }
}
@Override @Override
public void noMatches() { public void noMatches() {
@@ -211,7 +227,15 @@ public class MusicManager {
} }
} }
public void skip(int nbTrack) { public synchronized void removeFromQueue(int num) {
if (num == 1) {
skip(1);
} else {
scheduler.removeFromQueue(num);
}
}
public synchronized void skip(int nbTrack) {
if (!scheduler.getQueue().isEmpty()) { if (!scheduler.getQueue().isEmpty()) {
if (nbTrack >= scheduler.getQueue().size()) { if (nbTrack >= scheduler.getQueue().size()) {
nbTrack = 1; nbTrack = 1;
@@ -223,12 +247,12 @@ public class MusicManager {
} }
} }
public void voteSkip(CommandContext context) { public synchronized 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(); TrackScheduler.TrackInfo info = queue.peek();
if (getCurrentlyPlaying() == null) { if (getCurrentlyPlaying() == null || voiceChannel == null) {
return; return;
} }
@@ -257,7 +281,7 @@ public class MusicManager {
} }
} }
public void setVolume(int volume) { public synchronized void setVolume(int volume) {
player.setVolume(volume); player.setVolume(volume);
} }
@@ -265,7 +289,7 @@ public class MusicManager {
return scheduler; return scheduler;
} }
public ArrayList<AudioTrack> getAllQueuedTrack() { public synchronized ArrayList<AudioTrack> getAllQueuedTrack() {
ArrayList<AudioTrack> tracks = new ArrayList<>(); ArrayList<AudioTrack> tracks = new ArrayList<>();
Queue<TrackScheduler.TrackInfo> queue = scheduler.getQueue(); Queue<TrackScheduler.TrackInfo> queue = scheduler.getQueue();
@@ -21,16 +21,14 @@ enum SourceEnum {
} }
public class SourceFinder { public class SourceFinder {
private static final Pattern youtubePattern = Pattern.compile("^(?:https?://)?(?:(?:www\\.)?)?(?:youtube\\.com|youtu\\.be)/.*?(?:embed|e|v|watch.*?v=)?/?([-_a-z0-9]{10,})?(?:&?index=\\d+)?(?>(?:playlist\\?|&)?list=([^#\\\\&\\?]{12,}))?", Pattern.CASE_INSENSITIVE); private static final Pattern youtubePattern = Pattern.compile("^(?:https?://)?(?:(?:www\\.)?)?(?:youtube\\.com|youtu\\.be)/.*?(?:embed|e|v|watch.*?v=)?/?([-_a-z0-9]{10,})?(?:&?index=\\d+)?(?>(?:playlist\\?|&)?list=([^#\\\\&?]{12,}))?", Pattern.CASE_INSENSITIVE);
private static final Pattern soundcloudPattern = Pattern.compile("^(?:https?://)?(?:www\\.)?(?:m\\.)?soundcloud\\.com/([a-zA-Z0-9-_]+)/([a-zA-Z0-9-_]+)(?:\\\\?.*|)$", Pattern.CASE_INSENSITIVE); private static final Pattern soundcloudPattern = Pattern.compile("^(?:https?://)?(?:www\\.)?(?:m\\.)?soundcloud\\.com/([a-zA-Z0-9-_]+)/([a-zA-Z0-9-_]+)(?:\\\\?.*|)$", Pattern.CASE_INSENSITIVE);
private static Matcher youtubeMatcher;
private static Matcher soundcloudMatcher;
private static Matcher BandcampMatcher; private static Matcher BandcampMatcher;
private static Matcher vimeoMatcher; private static Matcher vimeoMatcher;
public static SourceEnum getSource(String url) { public static SourceEnum getSource(String url) {
youtubeMatcher = youtubePattern.matcher(url); Matcher youtubeMatcher = youtubePattern.matcher(url);
soundcloudMatcher = soundcloudPattern.matcher(url); Matcher soundcloudMatcher = soundcloudPattern.matcher(url);
if (youtubeMatcher.find()) if (youtubeMatcher.find())
return SourceEnum.Youtube; return SourceEnum.Youtube;
@@ -45,10 +43,11 @@ public class SourceFinder {
} }
public static String getIdentifier(String url) { public static String getIdentifier(String url) {
String identifier = switch (getSource(url)) { String identifier;
identifier = switch (getSource(url)) {
case Youtube, Soundcloud -> url; case Youtube, Soundcloud -> url;
case YTSearch -> "ytsearch:" + url; case YTSearch -> "ytsearch:" + url;
case Nothing -> null;
default -> null; default -> null;
}; };
@@ -14,13 +14,15 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.entities.TextChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*; import java.util.*;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
public class TrackScheduler extends AudioEventAdapter { public class TrackScheduler extends AudioEventAdapter {
class TrackInfo { static class TrackInfo {
private final AudioTrack track; private final AudioTrack track;
private final Member member; private final Member member;
@@ -56,7 +58,7 @@ public class TrackScheduler extends AudioEventAdapter {
} }
} }
private final Object topicLock = new Object(); private final static Logger logger = LoggerFactory.getLogger(TrackScheduler.class);
private final AudioPlayer player; private final AudioPlayer player;
private final Queue<TrackInfo> queue; private final Queue<TrackInfo> queue;
private TextChannel channel; private TextChannel channel;
@@ -67,7 +69,7 @@ public class TrackScheduler extends AudioEventAdapter {
this.queue = new LinkedBlockingQueue<>(); this.queue = new LinkedBlockingQueue<>();
} }
public void queue(AudioTrack track, Member member) { public synchronized void queue(AudioTrack track, Member member) {
// Calling startTrack with the noInterrupt set to true will start the track only if nothing is currently playing. If // Calling startTrack with the noInterrupt set to true will start the track only if nothing is currently playing. If
// something is playing, it returns false and does nothing. In that case the player was already playing so this // something is playing, it returns false and does nothing. In that case the player was already playing so this
// track goes to the queue instead. // track goes to the queue instead.
@@ -76,57 +78,52 @@ public class TrackScheduler extends AudioEventAdapter {
if (player.getPlayingTrack() == null) { if (player.getPlayingTrack() == null) {
player.startTrack(track, true); player.startTrack(track, true);
} }
} }
public String getOriginalTopic() { public synchronized String getOriginalTopic() {
synchronized (topicLock) {
return originalTopic; return originalTopic;
} }
}
public TextChannel getTextChannel() { public TextChannel getTextChannel() {
return channel; return channel;
} }
public void setTextChannel(TextChannel channel) { public synchronized void setTextChannel(TextChannel channel) {
this.channel = channel; this.channel = channel;
synchronized (topicLock) {
if (originalTopic == null) { if (originalTopic == null) {
originalTopic = channel.getTopic(); originalTopic = channel.getTopic();
} }
}
} }
public void resetTextChannel() { public synchronized void resetTextChannel() {
this.channel = null; this.channel = null;
} }
public Queue<TrackInfo> getQueue() { public synchronized Queue<TrackInfo> getQueue() {
return queue; return queue;
} }
public void resetTopic() { public synchronized void resetTopic() {
synchronized (topicLock) { if (channel != null && (originalTopic != null && !originalTopic.isEmpty())) {
if (channel != null && (originalTopic != null && !originalTopic.equals(""))) {
//channel.getManager().setTopic(topic).queue(); //channel.getManager().setTopic(topic).queue();
} }
originalTopic = null; originalTopic = null;
} }
} public synchronized void nextTrack(AudioPlayer player) {
public void nextTrack(AudioPlayer player) {
TrackInfo last = queue.poll(); TrackInfo last = queue.poll();
if (queue.peek() != null) { if (queue.peek() != null) {
player.startTrack(queue.peek().getTrack(), false); player.startTrack(queue.peek().getTrack(), false);
} } else
player.stopTrack();
} }
public void skipAndPlay(int nb) { public synchronized void skipAndPlay(int nb) {
if (nb == 0) if (nb == 0)
return; return;
@@ -140,7 +137,14 @@ public class TrackScheduler extends AudioEventAdapter {
} else { } else {
player.stopTrack(); player.stopTrack();
} }
}
protected synchronized void removeFromQueue(int index) {
ArrayList<TrackInfo> newQueue = new ArrayList<>(queue);
newQueue.remove(index - 1);
queue.clear();
queue.addAll(newQueue);
} }
@Override @Override
@@ -155,6 +159,7 @@ public class TrackScheduler extends AudioEventAdapter {
@Override @Override
public void onTrackStart(AudioPlayer player, AudioTrack track) { public void onTrackStart(AudioPlayer player, AudioTrack track) {
logger.debug("Starting track on guild {}: {}", channel.getGuild().getId(), track.getIdentifier());
// A track started playing // A track started playing
//channel.getManager().setTopic(":speaker: Now playing : " + track.getInfo().title).queue(); //channel.getManager().setTopic(":speaker: Now playing : " + track.getInfo().title).queue();
} }
@@ -163,11 +168,20 @@ public class TrackScheduler extends AudioEventAdapter {
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
resetTopic(); resetTopic();
if (endReason.mayStartNext) { // check if mayStartNext
if (endReason == AudioTrackEndReason.FINISHED || endReason == AudioTrackEndReason.LOAD_FAILED) {
//logger.debug("Queue size before next: " + queue.size());
nextTrack(player); nextTrack(player);
} else {
}
if (endReason == AudioTrackEndReason.STOPPED) {
synchronized (queue) {
queue.poll(); queue.poll();
} }
}
//logger.debug("Queue size after next: " + queue.size());
// endReason == FINISHED: A track finished or died by an exception (mayStartNext = true). // endReason == FINISHED: A track finished or died by an exception (mayStartNext = true).
// endReason == LOAD_FAILED: Loading of a track failed (mayStartNext = true). // endReason == LOAD_FAILED: Loading of a track failed (mayStartNext = true).
@@ -15,7 +15,7 @@ import java.util.List;
public class MusicPlayerAutoDisconnectThread implements Runnable { public class MusicPlayerAutoDisconnectThread implements Runnable {
MusicManager manager; final MusicManager manager;
public MusicPlayerAutoDisconnectThread(MusicManager musicManager) { public MusicPlayerAutoDisconnectThread(MusicManager musicManager) {
manager = musicManager; manager = musicManager;
@@ -109,7 +109,7 @@ public class MessageFunction {
return message.build(); return message.build();
} }
public static MessageEmbed buildViewQueueMessage(MusicManager manager, Member user) { public static MessageEmbed buildViewQueueMessage(MusicManager manager, Member user, boolean currentlyPlaying) {
ArrayList<AudioTrack> tracks = manager.getAllQueuedTrack(); ArrayList<AudioTrack> tracks = manager.getAllQueuedTrack();
AudioTrack current = manager.getCurrentlyPlaying(); AudioTrack current = manager.getCurrentlyPlaying();
@@ -119,7 +119,7 @@ public class MessageFunction {
int index = 0; int index = 0;
for (AudioTrack track: tracks) { for (AudioTrack track: tracks) {
if (track.getInfo().title.equals(current.getInfo().title)) { if (track.getInfo().title.equals(current.getInfo().title) && currentlyPlaying) {
message.addField("Track #" + ++index + " (Currently playing)", track.getInfo().title, false); message.addField("Track #" + ++index + " (Currently playing)", track.getInfo().title, false);
} else { } else {
message.addField("Track #" + ++index, track.getInfo().title, false); message.addField("Track #" + ++index, track.getInfo().title, false);
@@ -141,7 +141,7 @@ public class MessageFunction {
message.addField("Command", command.getCommandName(), false); message.addField("Command", command.getCommandName(), false);
message.addField("Description", command.getDescription(), false); message.addField("Description", command.getDescription(), false);
message.addField("Aliases", ((command.getAlias() == null || command.getAlias().length == 0) ? "None": Arrays.toString(command.getAlias()).replaceAll("[\\[\\]]", "")), false); message.addField("Aliases", ((command.getAlias() == null || command.getAlias().length == 0) ? "None": Arrays.toString(command.getAlias()).replaceAll("[\\[\\]]", "")), false);
message.addField("Usage", (command.getUsage() == null ? "No arguments defined" : command.getUsage()), false); message.addField("Usage", (command.getUsage() == null ? "No arguments defined" : command.getUsage().toString()), false);
return message.build(); return message.build();
} }
@@ -208,8 +208,15 @@ public class MessageFunction {
message.addField("Caused by command:", context.getCommand().getCommandName(), false); message.addField("Caused by command:", context.getCommand().getCommandName(), false);
message.addField("Exception:", error.getMessage(), false); message.addField("Exception:", error.getMessage(), false);
if (error.getCause() != null) { if (error.getCause() != null) {
message.addField("Caused by:", error.getCause().getMessage(), false); String cause;
if (error.getCause().getMessage() != null && !error.getCause().getMessage().isEmpty()) {
cause = error.getCause().getMessage();
} else {
cause = error.getCause().getClass().getName();
} }
message.addField("Caused by:", cause, false);
}
message.setFooter("Requested by " + context.getDiscordUser().getName(), context.getDiscordUser().getAvatarUrl()); message.setFooter("Requested by " + context.getDiscordUser().getName(), context.getDiscordUser().getAvatarUrl());
message.setTimestamp(OffsetDateTime.now()); message.setTimestamp(OffsetDateTime.now());
@@ -1,35 +0,0 @@
package netneutrality.utils;
/*
* Copyright (c) anthorob
*
* This file is closed-source. It should not be distributed or copied in any way or form
*/
import netneutrality.http.WebModule;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class YoutubeClass {
public static Pattern urlPattern = Pattern.compile("^(?:https?:\\/\\/)?(?:(?:www\\.)?)?(?:youtube\\.com|youtu\\.be)\\/.*?(?:embed|e|v|watch.*?v=)?\\/?([-_a-z0-9]{10,})?(?:&?index=\\d+)?(?>(?:playlist\\?|&)?list=([^#\\\\&\\?]{12,}))?", Pattern.CASE_INSENSITIVE);
private final static Pattern youtubeCode = Pattern.compile("^[A-Za-z0-9_-]{11}$");
public static String getCodeFromUrl(String url) {
Matcher matcher = urlPattern.matcher(url);
if (matcher.find()) {
if (matcher.group(1) != null) {
return matcher.group(1);
}
}
return "";
}
public static String getVideoTitle(String url) {
WebModule youtube = new WebModule(url).request();
return youtube.getTextInHtmlTag("<title>");
}
}