diff --git a/src/main/java/handiebot/command/CommandHandler.java b/src/main/java/handiebot/command/CommandHandler.java index 58e0113..cae19a9 100644 --- a/src/main/java/handiebot/command/CommandHandler.java +++ b/src/main/java/handiebot/command/CommandHandler.java @@ -14,7 +14,7 @@ import java.awt.*; */ public class CommandHandler { - private static String PREFIX = "!"; + public static String PREFIX = "!"; private final HandieBot bot; @@ -40,8 +40,10 @@ public class CommandHandler { this.bot.getMusicPlayer().skipTrack(guild); } else if (command.equals("help")){ this.sendHelpInfo(user); - } else if (command.equals("playnow") && args.length == 1){ - + } else if (command.equals("queue") && args.length == 0){ + this.bot.getMusicPlayer().showQueueList(guild); + } else if (command.equals("repeat")){ + this.bot.getMusicPlayer().toggleRepeat(guild); } } } diff --git a/src/main/java/handiebot/lavaplayer/MusicPlayer.java b/src/main/java/handiebot/lavaplayer/MusicPlayer.java index ef70a9a..039da59 100644 --- a/src/main/java/handiebot/lavaplayer/MusicPlayer.java +++ b/src/main/java/handiebot/lavaplayer/MusicPlayer.java @@ -7,9 +7,11 @@ import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import handiebot.command.CommandHandler; import sx.blah.discord.handle.obj.IChannel; import sx.blah.discord.handle.obj.IGuild; import sx.blah.discord.handle.obj.IVoiceChannel; +import sx.blah.discord.util.EmbedBuilder; import java.util.HashMap; import java.util.List; @@ -34,6 +36,49 @@ public class MusicPlayer { AudioSourceManagers.registerRemoteSources(playerManager); } + /** + * Toggles the playlist's repeating. + * @param guild The guild to perform the action on. + */ + public void toggleRepeat(IGuild guild){ + GuildMusicManager musicManager = this.getGuildMusicManager(guild); + musicManager.scheduler.setRepeat(!musicManager.scheduler.isRepeating()); + this.getMessageChannel(guild).sendMessage("**Repeat** is now *"+(musicManager.scheduler.isRepeating() ? "On" : "Off")+"*."); + } + + /** + * Sends a formatted message to the guild about the first few items in a queue. + * @param guild The guild to show the queue for. + */ + public void showQueueList(IGuild guild){ + GuildMusicManager musicManager = this.getGuildMusicManager(guild); + List tracks = musicManager.scheduler.queueList(); + if (tracks.size() == 0) { + this.getMessageChannel(guild).sendMessage("The queue is empty. Use **"+ CommandHandler.PREFIX+"play** *URL* to add songs."); + } else { + EmbedBuilder builder = new EmbedBuilder(); + builder.withColor(255, 0, 0); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < (tracks.size() <= 10 ? tracks.size() : 10); i++) { + sb.append(i+1); + sb.append(". "); + sb.append('['); + sb.append(tracks.get(i).getInfo().title); + sb.append("]("); + sb.append(tracks.get(i).getInfo().uri); + sb.append(") ["); + int seconds = (int) (tracks.get(i).getInfo().length/1000); + int minutes = seconds / 60; + sb.append(minutes); + sb.append(":"); + sb.append(seconds % 60); + sb.append("]\n"); + } + builder.appendField("Showing " + (tracks.size() <= 10 ? tracks.size() : "the first 10") + " tracks.", sb.toString(), false); + this.getMessageChannel(guild).sendMessage(builder.build()); + } + } + /** * Loads a URL to the queue, or outputs an error message if it fails. * @param guild The guild to load the URL to. @@ -81,7 +126,7 @@ public class MusicPlayer { if (voiceChannel != null){ musicManager.scheduler.queue(track); IChannel channel = this.getMessageChannel(guild); - channel.sendMessage("Added ["+track.getInfo().title+"] to the queue."); + channel.sendMessage("Added **"+track.getInfo().title+"** to the queue."); } } @@ -117,11 +162,11 @@ public class MusicPlayer { * @return The voice channel the bot is now connected to. */ private IVoiceChannel connectToMusicChannel(IGuild guild){ - for (IVoiceChannel voiceChannel : guild.getVoiceChannelsByName(CHANNEL_NAME)){ - if (!voiceChannel.isConnected()) { - voiceChannel.join(); - return voiceChannel; - } + List voiceChannels = guild.getVoiceChannelsByName(CHANNEL_NAME); + if (voiceChannels.size() == 1){ + if (!voiceChannels.get(0).isConnected()) + voiceChannels.get(0).join(); + return voiceChannels.get(0); } IVoiceChannel voiceChannel = guild.createVoiceChannel(CHANNEL_NAME); voiceChannel.join(); diff --git a/src/main/java/handiebot/lavaplayer/TrackScheduler.java b/src/main/java/handiebot/lavaplayer/TrackScheduler.java index 555a6f4..18fff1a 100644 --- a/src/main/java/handiebot/lavaplayer/TrackScheduler.java +++ b/src/main/java/handiebot/lavaplayer/TrackScheduler.java @@ -6,6 +6,8 @@ import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -16,6 +18,8 @@ public class TrackScheduler extends AudioEventAdapter { private final AudioPlayer player; private final BlockingQueue queue; + private boolean repeat = false; + private AudioTrack currentTrack = null; /** * Constructs a new track scheduler with the given player. @@ -26,6 +30,22 @@ public class TrackScheduler extends AudioEventAdapter { this.queue = new LinkedBlockingQueue<>(); } + /** + * Sets whether or not songs get placed back into the queue once they're played. + * @param value True if the playlist should repeat. + */ + public void setRepeat(boolean value){ + this.repeat = value; + } + + /** + * Returns whether or not repeating is enabled. + * @return True if repeating, false otherwise. + */ + public boolean isRepeating(){ + return this.repeat; + } + /** * Add the next track to the queue or play right away if nothing is in the queue. * @param track The track to play or add to the queue. @@ -41,7 +61,12 @@ public class TrackScheduler extends AudioEventAdapter { * Starts the next track, stopping the current one if it's playing. */ public void nextTrack(){ - player.startTrack(queue.poll(), false); + AudioTrack track = queue.poll(); + player.startTrack(track, false); + this.currentTrack = track; + if (this.repeat){ + this.queue.add(track); + } } @Override @@ -49,10 +74,19 @@ public class TrackScheduler extends AudioEventAdapter { if (endReason.mayStartNext){ nextTrack(); } else { + this.currentTrack = null; System.out.println(endReason.toString()); } } + /** + * Returns a list of tracks in the queue. + * @return A list of tracks in the queue. + */ + public List queueList(){ + return new ArrayList<>(this.queue); + } + @Override public void onTrackException(AudioPlayer player, AudioTrack track, FriendlyException exception){ exception.printStackTrace();