+ (handler.toggleLoopQueue(c.getGuild(), "autoplay") ? "on.\nIt will end once someone joins the music channel." : "off."))
.queue();
return new CommandResult(CommandResultType.SUCCESS);
} else {
return new CommandResult(CommandResultType.INVALIDARGS, "You are currently not alone in the music channel, therefore this feature is disabled.");
}
- }, "", null, "Auto-queues related track of the last track when you are alone!",
- Arrays.asList(" Note: it will autoplay indefinitely until you toggle it again or someone joins."));
+ }, "", null, "Auto-queues related tracks when you are alone!",
+ Arrays.asList(" * Currently only works if the last track in the queue is a youtube video.", " Note: it will autoplay indefinitely until you toggle it again or someone joins."));
registerSubCommand("loop", Arrays.asList("l", "loopqueue"), (c, u, m, a) -> {
return new CommandResult(CommandResultType.INVALIDARGS, "Please enter a valid timestamp with colons.");
} catch (IllegalArgumentException e) {
return new CommandResult(CommandResultType.INVALIDARGS, e.getMessage());
}
}, "[+/-][hr:]<min:sec>", Arrays.asList("4:52:21", "2:00", "+30:00", "-1:23:45"), "Set the playing position in the current track!",
Arrays.asList("timestamps without signs are absolute, whereas `+`/`-` means go forward or backward from the current position for the amount of time specified respectively.", " * the person who requested the current track can always set the position, regardless of perms."),
registerSubCommand("removetrack", Arrays.asList("rt", "r", "skiptrack", "st"), (c, u, m, a) -> {
if(a.length > 0) {
try {
int num = Integer.parseInt(a[0]);
if(num == 1) return new CommandResult(CommandResultType.INVALIDARGS, "You cannot remove the current track from the queue with this command. Use !desp music skip instead.");
if(num < 1) return new CommandResult(CommandResultType.INVALIDARGS, "The index you entered is invalid.");
return new CommandResult(CommandResultType.INVALIDARGS, "Please valid indices.");
}
}, "<fromindex> <toindex>", Arrays.asList("2 3"), "Move a track to the specified index.", Arrays.asList(" * you can also run this command regardless of perms if you are alone with the bot.")
c.sendMessage("Successfully shuffled the queue.").queue();
return new CommandResult(CommandResultType.SUCCESS);
} else {
return new CommandResult(CommandResultType.INVALIDARGS, "You are currently not alone in the music channel, therefore this feature is disabled.");
}
}, "", null, "Shuffle the tracks in the queue when you are alone!", null);
//TODO make vote system for this
registerSubCommand("clear", Arrays.asList("disconnect", "dc", "stop", "clearqueue"), (c, u, m, a) -> {
handler.stopAndClearQueue(c.getGuild());
c.sendMessage("The queue has been cleared.").queue();
return new CommandResult(CommandResultType.SUCCESS);
}, "", null, "Clear the queue and stop the player.", Arrays.asList(" * you can also run this command regardless of perms if you are alone with the bot.")
return new CommandResult(CommandResultType.FAILURE, e.getMessage());
} catch(NullPointerException e) {
return new CommandResult(CommandResultType.INVALIDARGS, "There is nothing playing currently! Please specify a song title to search the lyrics up.");
} catch(IOException e) {
return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
}
}, "[search words]", Arrays.asList(""), "Search some lyrics up!", Arrays.asList(" * if you did not specify any search words, the bot will try to fetch the lyrics of the current track playing, if any."));
//TODO equalizer persistence?
//make this premium?
registerSubCommand("equalizer", Arrays.asList("eq"), (c, u, m, a) -> {
GuildMusicManager mm = handler.getGuildMusicManager(c.getGuild());
Float[] vals;
if(a.length == 0) {
vals = mm.getCurrentGain();
} else {
try {
try {
if(a.length != 15) throw new NumberFormatException();
vals = new Float[15];
for(int i = 0; i < a.length; i++) {
vals[i] = Float.parseFloat(a[i]);
}
mm.setGain(0, vals);
} catch(NumberFormatException e) {
vals = mm.setPresetGain(a[0]);
}
} catch(IllegalArgumentException e2) {
return new CommandResult(CommandResultType.INVALIDARGS, e2.getMessage());
}
}
//formatting
DecimalFormat df = new DecimalFormat("0.00");
df.setPositivePrefix("+");
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("Current equalizer graph");
eb.appendDescription("```\n");
for(double line = 0.25; line >= -0.25; line -= 0.05) {
return new CommandResult(CommandResultType.SUCCESS);
}, "[bandvalues/presetname]", Arrays.asList("", "0.09 0.07 0.07 0.01 0 0 -0.02 -0.02 0.03 0.03 0.05 0.07 0.09 0.1 0.1", "bassboost"), "Sets the equalizer for the music player in this guild!",
Arrays.asList("Accepts 15 bands with values ranging from -0.25 to 0.25, where -0.25 is muted and 0.25 is double volume.", "* presets include: `bassboost`, `default`, `rock`.", "Input nothing to return the current settings.", "",
"Note: you might experience some audio cracking for band values >0.1, since amplifying volumes remotely does not work well.", "It is recommended to use values from -0.25 to 0.1, and turning discord volume up instead.")
if(Arrays.asList("move", "clear").contains(sub.getName())) { //should always be connected to vc
if(channel.getGuild().getAudioManager().getConnectedChannel().getMembers().size() == 2) { //alone; no need to check if the other member is requester, since its checked before
CommandResult res = super.execute(channel, author, msg, args); //pass to subcommand handler for perms checking
if(res.getResultType() == CommandResultType.NOPERMS && Arrays.asList("forceskip", "skip", "setposition", "removetrack").contains(sub.getName())) { //add back info to command result
res = new CommandResult(CommandResultType.INVALIDARGS, res.getMessage().getContentRaw().split(" to execute")[0] + ", or have requested the track to execute this command.");
}
return res;
}
//maybe move the lyrics stuff elsewhere?
private final String geniusAuth = DiscordBot.tokens.getProperty("genius");
//annotated usually isnt actual lyrics, but the following are known to be some
//private ExecutorService executor = Executors.newCachedThreadPool(); //unfortunately i need to finish the api search to get the url to start the html scrape, which means i cannot use future for multithread here
public List<MessageEmbed> getLyrics(String search) throws IOException { //DONE dont splice words between embeds; make whole sentence to be spliced instead
//appends metadata portion to the given embed (should be the last one)
private void setFinalLyricsEmbed(EmbedBuilder eb, JSONObject main, Element html) { //change the format for the supplementary info in artists and albums from italic to sth else?
try {
String name = main.getJSONObject("primary_artist").getString("name");
JSONObject preload = new JSONObject(StringEscapeUtils.unescapeJson(temp));
JSONObject song = preload.getJSONObject("entities").getJSONObject("songs").getJSONObject(Integer.toString(preload.getJSONObject("songPage").getInt("song")));
//parse albums
try {
StringBuilder sb = new StringBuilder();
String album = IntStream.range(0, song.getJSONArray("trackingData").length()).mapToObj(i -> song.getJSONArray("trackingData").getJSONObject(i)).filter(obj -> obj.getString("key").equals("Primary Album")).findFirst().get().getString("value").trim();