package me.chayapak1.chomens_bot.commands; import me.chayapak1.chomens_bot.Bot; import me.chayapak1.chomens_bot.command.Command; import me.chayapak1.chomens_bot.command.CommandContext; import me.chayapak1.chomens_bot.plugins.MusicPlayerPlugin; import me.chayapak1.chomens_bot.song.Song; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.NamedTextColor; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; public class MusicCommand implements Command { private Path root; public String name() { return "music"; } public String description() { return "Plays music"; } public List usage() { final List usages = new ArrayList<>(); usages.add("play <{song|URL}>"); usages.add("stop"); usages.add("loop "); usages.add("list [{directory}]"); usages.add("skip"); usages.add("nowplaying"); usages.add("queue"); usages.add("goto"); usages.add("pause"); usages.add("resume"); return usages; } public List alias() { final List aliases = new ArrayList<>(); aliases.add("song"); return aliases; } public int trustLevel() { return 0; } public Component execute(CommandContext context, String[] args, String[] fullArgs) { root = Path.of(context.bot().music().SONG_DIR.getPath()); switch (args[0]) { case "play" -> { return play(context, args); } case "stop" -> stop(context); case "loop" -> { return loop(context, args); } case "list" -> { return list(context, args); } case "skip" -> { return skip(context); } case "nowplaying" -> { return nowplaying(context); } case "queue" -> queue(context); case "goto" -> { return goTo(context, args); } case "pause", "resume" -> { return pause(context); } default -> { return Component.text("Invalid argument").color(NamedTextColor.RED); } } return Component.text("success"); } public Component play (CommandContext context, String[] args) { final MusicPlayerPlugin player = context.bot().music(); final String _path = String.join(" ", Arrays.copyOfRange(args, 1, args.length)); final Path path = Path.of(root.toString(), _path); try { if (!path.toString().contains("http")) player.loadSong(path); else player.loadSong(new URL(_path)); } catch (MalformedURLException e) { return Component.text("Invalid URL").color(NamedTextColor.RED); } return Component.text("success"); } public void stop (CommandContext context) { final Bot bot = context.bot(); bot.music().stopPlaying(); bot.music().songQueue().clear(); } public Component loop (CommandContext context, String[] args) { final Bot bot = context.bot(); int loop; switch (args[1]) { case "off" -> { loop = 0; context.sendOutput( Component.empty() .append(Component.text("Looping is now ")) .append(Component.text("disabled").color(NamedTextColor.RED)) ); } case "current" -> { loop = 1; context.sendOutput( Component.empty() .append(Component.text("Now looping ")) .append(bot.music().currentSong().name.color(NamedTextColor.GOLD)) ); } case "all" -> { loop = 2; context.sendOutput(Component.text("Now looping every song")); } default -> { return Component.text("Invalid argument").color(NamedTextColor.RED); } } bot.music().loop(loop); return Component.text("success"); } public Component list (CommandContext context, String[] args) { final String prefix = context.prefix(); final Path _path = Path.of(root.toString(), String.join(" ", args)); final Path path = (args.length < 2) ? root : _path; final String[] filenames = path.toFile().list(); if (filenames == null) return Component.text("Directory doesn't exist").color(NamedTextColor.RED); final List list = new ArrayList<>(); int i = 0; for (String filename : filenames) { final String pathString = path.toString(); final File file = new File(Paths.get(pathString, filename).toUri()); Path location; try { location = path; } catch (IllegalArgumentException e) { location = Paths.get(""); // wtf mabe } final String joinedPath = (args.length < 2) ? filename : Paths.get(location.getFileName().toString(), filename).toString(); list.add( Component .text(filename, (i++ & 1) == 0 ? NamedTextColor.YELLOW : NamedTextColor.GOLD) .clickEvent( ClickEvent.suggestCommand( prefix + "music" + // ? How do I make this dynamic? (file.isFile() ? " play " : " list ") + joinedPath.replace("'", "\\'") ) ) ); } final Component component = Component.join(JoinConfiguration.separator(Component.space()), list); context.sendOutput(component); return Component.text("success"); } public Component skip (CommandContext context) { final MusicPlayerPlugin music = context.bot().music(); if (music.currentSong() == null) return Component.text("No song is currently playing").color(NamedTextColor.RED); context.sendOutput( Component.empty() .append(Component.text("Skipping ")) .append(music.currentSong().name.color(NamedTextColor.GOLD)) ); music.skip(); return Component.text("success"); } public Component nowplaying (CommandContext context) { final Bot bot = context.bot(); final Song song = bot.music().currentSong(); if (song == null) return Component.text("No song is currently playing").color(NamedTextColor.RED); context.sendOutput( Component.empty() .append(Component.text("Now playing ")) .append(song.name.color(NamedTextColor.GOLD)) ); return Component.text("success"); } public void queue (CommandContext context) { final Bot bot = context.bot(); final LinkedList queue = bot.music().songQueue(); final List queueWithNames = new ArrayList<>(); for (Song song : queue) queueWithNames.add(song.name); context.sendOutput( Component.empty() .append(Component.text("Queue: ").color(NamedTextColor.GREEN)) .append(Component.join(JoinConfiguration.separator(Component.text(", ")), queueWithNames).color(NamedTextColor.AQUA)) ); } // lazy fix for java using "goto" as keyword real public Component goTo (CommandContext context, String[] args) { final Bot bot = context.bot(); final Song currentSong = bot.music().currentSong(); final long milliseconds; try { milliseconds = Long.parseLong(args[1]); } catch (NumberFormatException e) { return Component.text("Invalid timestamp").color(NamedTextColor.RED); } if (currentSong == null) return Component.text("No song is currently playing").color(NamedTextColor.RED); if (milliseconds < 0 || milliseconds > currentSong.length) return Component.text("Invalid timestamp").color(NamedTextColor.RED); currentSong.setTime(milliseconds); return Component.text("success"); } public Component pause (CommandContext context) { final Bot bot = context.bot(); final Song currentSong = bot.music().currentSong(); if (currentSong == null) return Component.text("No song is currently playing").color(NamedTextColor.RED); if (currentSong.paused) { currentSong.play(); context.sendOutput(Component.text("Resumed the current song")); } else { currentSong.pause(); context.sendOutput(Component.text("Paused the current song")); } return Component.text("success"); } }