From c77540934e557844589db2ee45570a99c2b6fb8c Mon Sep 17 00:00:00 2001 From: Andrew Lalis Date: Wed, 21 Jun 2017 10:36:10 +0200 Subject: [PATCH] Fixed loading a playlist from a file. --- src/main/java/handiebot/HandieBot.java | 7 +-- .../handiebot/command/CommandHandler.java | 12 ++--- .../lavaplayer/GuildMusicManager.java | 2 +- .../handiebot/lavaplayer/MusicPlayer.java | 30 ++++++++----- .../java/handiebot/lavaplayer/Playlist.java | 45 +++++++++++++------ .../handiebot/lavaplayer/TrackScheduler.java | 13 +++--- src/main/java/handiebot/view/BotLog.java | 37 +++++++++++++-- src/main/java/handiebot/view/View.form | 6 ++- 8 files changed, 107 insertions(+), 45 deletions(-) diff --git a/src/main/java/handiebot/HandieBot.java b/src/main/java/handiebot/HandieBot.java index 9c06591..ec09d16 100644 --- a/src/main/java/handiebot/HandieBot.java +++ b/src/main/java/handiebot/HandieBot.java @@ -21,9 +21,9 @@ public class HandieBot { public static final String APPLICATION_NAME = "HandieBot"; private static final String TOKEN = "MjgzNjUyOTg5MjEyNjg4Mzg0.C45A_Q.506b0G6my1FEFa7_YY39lxLBHUY"; - public static IDiscordClient client; + private static IDiscordClient client; public static View view; - public static BotWindow window; + private static BotWindow window; public static BotLog log; private CommandHandler commandHandler; @@ -58,10 +58,11 @@ public class HandieBot { * Safely shuts down the bot on all guilds. */ public static void quit(){ + log.log(BotLog.TYPE.INFO, "Shutting down the bot."); musicPlayer.quitAll(); client.logout(); window.dispose(); - + System.exit(0); } } diff --git a/src/main/java/handiebot/command/CommandHandler.java b/src/main/java/handiebot/command/CommandHandler.java index da1392e..1b2b0d2 100644 --- a/src/main/java/handiebot/command/CommandHandler.java +++ b/src/main/java/handiebot/command/CommandHandler.java @@ -39,28 +39,28 @@ public class CommandHandler { if (command.equals("play")){ //Play or queue a song. if (args.length == 1) { - this.bot.musicPlayer.loadToQueue(guild, args[0]); + HandieBot.musicPlayer.loadToQueue(guild, args[0]); } else if (args.length == 0){ - this.bot.musicPlayer.playQueue(guild); + HandieBot.musicPlayer.playQueue(guild); } } else if (command.equals("skip") && args.length == 0){ //Skip the current song. - this.bot.musicPlayer.skipTrack(guild); + HandieBot.musicPlayer.skipTrack(guild); } else if (command.equals("help")){ //Send a PM to the user with help info. this.sendHelpInfo(user);//TODO finish the help command and fill in with new descriptions each time. } else if (command.equals("queue") && args.length == 0){ //Display the first few items of the queue. - this.bot.musicPlayer.showQueueList(guild); + HandieBot.musicPlayer.showQueueList(guild); } else if (command.equals("repeat")){ //Toggle repeat. - //TODO implement repeat command. + HandieBot.musicPlayer.toggleRepeat(guild); } else if (command.equals("clear")){ //TODO clear command. } else if (command.equals("quit")){ //Quit the application. channel.sendMessage("Quitting HandieBot functions."); - this.bot.musicPlayer.quit(guild); + HandieBot.musicPlayer.quit(guild); } else if (command.equals("playlist")){ //Do playlist actions. //TODO perform actions! diff --git a/src/main/java/handiebot/lavaplayer/GuildMusicManager.java b/src/main/java/handiebot/lavaplayer/GuildMusicManager.java index 54f8268..bd5320f 100644 --- a/src/main/java/handiebot/lavaplayer/GuildMusicManager.java +++ b/src/main/java/handiebot/lavaplayer/GuildMusicManager.java @@ -16,7 +16,7 @@ public class GuildMusicManager { public GuildMusicManager(AudioPlayerManager manager, IGuild guild){ this.player = manager.createPlayer(); - this.scheduler = new TrackScheduler(this.player, guild); + this.scheduler = new TrackScheduler(this.player, guild, manager); this.player.addListener(this.scheduler); } diff --git a/src/main/java/handiebot/lavaplayer/MusicPlayer.java b/src/main/java/handiebot/lavaplayer/MusicPlayer.java index 364ba99..e4ffb5d 100644 --- a/src/main/java/handiebot/lavaplayer/MusicPlayer.java +++ b/src/main/java/handiebot/lavaplayer/MusicPlayer.java @@ -61,7 +61,7 @@ public class MusicPlayer { */ private GuildMusicManager getMusicManager(IGuild guild){ if (!this.musicManagers.containsKey(guild)){ - log.log(BotLog.TYPE.MUSIC, "Creating new music manager and audio provider for guild: "+guild.getName()); + log.log(BotLog.TYPE.MUSIC, guild, "Creating new music manager and audio provider for guild: "+guild.getName()); this.musicManagers.put(guild, new GuildMusicManager(this.playerManager, guild)); guild.getAudioManager().setAudioProvider(this.musicManagers.get(guild).getAudioProvider()); } @@ -78,7 +78,7 @@ public class MusicPlayer { if (!this.chatChannels.containsKey(guild)){ List channels = guild.getChannelsByName(CHANNEL_NAME.toLowerCase()); if (channels.isEmpty()){ - log.log(BotLog.TYPE.MUSIC, "No chat channel found, creating a new one."); + log.log(BotLog.TYPE.MUSIC, guild, "No chat channel found, creating a new one."); this.chatChannels.put(guild, guild.createChannel(CHANNEL_NAME.toLowerCase())); } else { this.chatChannels.put(guild, channels.get(0)); @@ -97,7 +97,7 @@ public class MusicPlayer { if (!this.voiceChannels.containsKey(guild)){ List channels = guild.getVoiceChannelsByName(CHANNEL_NAME); if (channels.isEmpty()){ - log.log(BotLog.TYPE.MUSIC, "No voice channel found, creating a new one."); + log.log(BotLog.TYPE.MUSIC, guild, "No voice channel found, creating a new one."); this.voiceChannels.put(guild, guild.createVoiceChannel(CHANNEL_NAME)); } else { this.voiceChannels.put(guild, channels.get(0)); @@ -106,6 +106,16 @@ public class MusicPlayer { return this.voiceChannels.get(guild); } + /** + * Toggles the repeating of songs for a particular guild. + * @param guild The guild to repeat for. + */ + public void toggleRepeat(IGuild guild){ + GuildMusicManager musicManager = this.getMusicManager(guild); + + musicManager.scheduler.setRepeat(!musicManager.scheduler.isRepeating()); + } + /** * Sends a formatted message to the guild about the first few items in a queue. */ @@ -124,13 +134,12 @@ public class MusicPlayer { sb.append(tracks.get(i).getInfo().title); sb.append("]("); sb.append(tracks.get(i).getInfo().uri); - sb.append(") ["); + 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"); + seconds = seconds % 60; + String time = String.format(" [%d:%02d]\n", minutes, seconds); + sb.append(time); } builder.withTimestamp(System.currentTimeMillis()); builder.appendField("Showing " + (tracks.size() <= 10 ? tracks.size() : "the first 10") + " track"+(tracks.size() > 1 ? "s" : "")+".", sb.toString(), false); @@ -147,7 +156,6 @@ public class MusicPlayer { this.playerManager.loadItemOrdered(getMusicManager(guild), trackURL, new AudioLoadResultHandler() { @Override public void trackLoaded(AudioTrack audioTrack) { - log.log(BotLog.TYPE.MUSIC, "Track successfully loaded: "+audioTrack.getInfo().title); addToQueue(guild, audioTrack); } @@ -164,11 +172,13 @@ public class MusicPlayer { @Override public void noMatches() { + log.log(BotLog.TYPE.ERROR, guild, "No matches found for: "+trackURL); new DisappearingMessage(getChatChannel(guild), "Unable to find a result for: "+trackURL, 3000); } @Override public void loadFailed(FriendlyException e) { + log.log(BotLog.TYPE.ERROR, guild, "Unable to load song: "+trackURL+". "+e.getMessage()); new DisappearingMessage(getChatChannel(guild), "Unable to load. "+e.getMessage(), 3000); } }); @@ -220,7 +230,7 @@ public class MusicPlayer { */ public void skipTrack(IGuild guild){ getMusicManager(guild).scheduler.nextTrack(); - log.log(BotLog.TYPE.MUSIC, "Skipping the current track. "); + log.log(BotLog.TYPE.MUSIC, guild, "Skipping the current track. "); new DisappearingMessage(getChatChannel(guild), "Skipping the current track.", 3000); } diff --git a/src/main/java/handiebot/lavaplayer/Playlist.java b/src/main/java/handiebot/lavaplayer/Playlist.java index 16c7fb1..3d2a8f8 100644 --- a/src/main/java/handiebot/lavaplayer/Playlist.java +++ b/src/main/java/handiebot/lavaplayer/Playlist.java @@ -2,10 +2,10 @@ package handiebot.lavaplayer; import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; -import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import handiebot.view.BotLog; import java.io.*; import java.nio.file.Files; @@ -13,6 +13,9 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.concurrent.ExecutionException; + +import static handiebot.HandieBot.log; /** * @author Andrew Lalis @@ -24,7 +27,7 @@ public class Playlist { private String name; private long creatorUID; - List tracks; + private List tracks; /** * Creates an empty playlist template. @@ -41,9 +44,9 @@ public class Playlist { * Creates a playlist from a file with the given name. * @param name The name of the file. */ - public Playlist(String name){ + public Playlist(String name, AudioPlayerManager playerManager){ this.name = name; - this.load(); + this.load(playerManager); } public String getName(){ @@ -74,6 +77,15 @@ public class Playlist { this.tracks.remove(track); } + /** + * Copies all tracks from a specified playlist to this one. + * @param other The other playlist to make a copy of. + */ + public void copyFrom(Playlist other){ + this.tracks.clear(); + other.getTracks().forEach(track -> this.tracks.add(track.makeClone())); + } + /** * Returns the next track, i.e. the first one in the list, and removes it from the internal list. * @return The AudioTrack that should be played next. @@ -87,7 +99,7 @@ public class Playlist { /** * Returns the next track to be played, and re-adds it to the end of the playlist, as it would do in a loop. - * @return + * @return The next track to be played. */ public AudioTrack getNextTrackAndRequeue(boolean shouldShuffle){ if (this.tracks.isEmpty()){ @@ -122,12 +134,12 @@ public class Playlist { File playlistDir = new File(homeDir+"/.handiebot/playlist"); if (!playlistDir.exists()){ if (!playlistDir.mkdirs()){ - System.out.println("Unable to make directory: "+playlistDir.getPath()); + log.log(BotLog.TYPE.ERROR, "Unable to make directory: "+playlistDir.getPath()); return; } } File playlistFile = new File(playlistDir.getPath()+"/"+this.name.replace(" ", "_")+".txt"); - System.out.println("Saving playlist to: "+playlistFile.getAbsolutePath()); + log.log(BotLog.TYPE.INFO, "Saving playlist to: "+playlistFile.getAbsolutePath()); try(Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(playlistFile)))){ writer.write(this.name+'\n'); writer.write(Long.toString(this.creatorUID)+'\n'); @@ -137,6 +149,7 @@ public class Playlist { writer.write('\n'); } } catch (FileNotFoundException e) { + log.log(BotLog.TYPE.ERROR, "Unable to find file to write playlist: "+this.name); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); @@ -146,8 +159,9 @@ public class Playlist { /** * Loads the playlist from a file with the playlist's name. */ - public void load(){//TODO Make load work!!! + public void load(AudioPlayerManager playerManager){ String path = System.getProperty("user.home")+"/.handiebot/playlist/"+this.name.replace(" ", "_")+".txt"; + log.log(BotLog.TYPE.INFO, "Loading playlist from: "+path); File playlistFile = new File(path); if (playlistFile.exists()){ try { @@ -156,20 +170,16 @@ public class Playlist { this.creatorUID = Long.parseLong(lines.remove(0)); int trackCount = Integer.parseInt(lines.remove(0)); this.tracks = new ArrayList<>(trackCount); - AudioPlayerManager pm = new DefaultAudioPlayerManager(); for (int i = 0; i < trackCount; i++){ - System.out.println("Loading item "+i); String url = lines.remove(0); - pm.loadItem(url, new AudioLoadResultHandler() { + playerManager.loadItem(url, new AudioLoadResultHandler() { @Override public void trackLoaded(AudioTrack audioTrack) { - System.out.println("Added track"); tracks.add(audioTrack); } @Override public void playlistLoaded(AudioPlaylist audioPlaylist) { - System.out.println("Playlist loaded."); //Do nothing. This should not happen. } @@ -184,9 +194,16 @@ public class Playlist { System.out.println("Load failed: "+e.getMessage()); //Do nothing. This should not happen. } - }); + }).get(); } } catch (IOException e) { + log.log(BotLog.TYPE.ERROR, "IOException while loading playlist ["+this.name+"]. "+e.getMessage()); + e.printStackTrace(); + } catch (InterruptedException e) { + log.log(BotLog.TYPE.ERROR, "Loading of playlist ["+this.name+"] interrupted. "+e.getMessage()); + e.printStackTrace(); + } catch (ExecutionException e) { + log.log(BotLog.TYPE.ERROR, "Execution exception while loading playlist ["+this.name+"]. "+e.getMessage()); e.printStackTrace(); } } diff --git a/src/main/java/handiebot/lavaplayer/TrackScheduler.java b/src/main/java/handiebot/lavaplayer/TrackScheduler.java index 5fbddcc..6e42fdd 100644 --- a/src/main/java/handiebot/lavaplayer/TrackScheduler.java +++ b/src/main/java/handiebot/lavaplayer/TrackScheduler.java @@ -1,6 +1,7 @@ package handiebot.lavaplayer; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter; import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; @@ -24,7 +25,7 @@ public class TrackScheduler extends AudioEventAdapter { private Playlist activePlaylist; - private boolean repeat = false; + private boolean repeat = true; private boolean shuffle = false; private IGuild guild; @@ -33,11 +34,11 @@ public class TrackScheduler extends AudioEventAdapter { * Constructs a new track scheduler with the given player. * @param player The audio player this scheduler uses. */ - public TrackScheduler(AudioPlayer player, IGuild guild){ + public TrackScheduler(AudioPlayer player, IGuild guild, AudioPlayerManager playerManager){ this.player = player; this.guild = guild; - this.activePlaylist = new Playlist("HandieBot Active Playlist", 283652989212688384L); - //this.activePlaylist = new Playlist("HandieBot Active Playlist"); + //this.activePlaylist = new Playlist("HandieBot Active Playlist", 283652989212688384L); + this.activePlaylist = new Playlist("HandieBot Active Playlist", playerManager); } /** @@ -130,7 +131,7 @@ public class TrackScheduler extends AudioEventAdapter { @Override public void onTrackStart(AudioPlayer player, AudioTrack track) { - log.log(BotLog.TYPE.MUSIC, "Started audio track: "+track.getInfo().title); + log.log(BotLog.TYPE.MUSIC, this.guild, "Started audio track: "+track.getInfo().title); List channels = this.guild.getChannelsByName(MusicPlayer.CHANNEL_NAME.toLowerCase()); if (channels.size() > 0){ IMessage message = channels.get(0).sendMessage("Now playing: **"+track.getInfo().title+"**."); @@ -146,7 +147,7 @@ public class TrackScheduler extends AudioEventAdapter { System.out.println("Moving to next track."); nextTrack(); } else { - log.log(BotLog.TYPE.ERROR, "Unable to go to the next track. Reason: "+endReason.name()); + log.log(BotLog.TYPE.ERROR, this.guild, "Unable to go to the next track. Reason: "+endReason.name()); System.out.println(endReason.toString()); } } diff --git a/src/main/java/handiebot/view/BotLog.java b/src/main/java/handiebot/view/BotLog.java index c473b96..2e43db4 100644 --- a/src/main/java/handiebot/view/BotLog.java +++ b/src/main/java/handiebot/view/BotLog.java @@ -1,5 +1,7 @@ package handiebot.view; +import sx.blah.discord.handle.obj.IGuild; + import javax.swing.*; import javax.swing.text.BadLocationException; import javax.swing.text.Style; @@ -21,10 +23,19 @@ public class BotLog { public enum TYPE { INFO, MUSIC, - ERROR + ERROR, + COMMAND } + //Styles for output to the console. private Map logStyles; + private static Map logStyleColors = new HashMap(){{ + put(INFO, new Color(22, 63, 160)); + put(MUSIC, new Color(51, 175, 66)); + put(ERROR, new Color(255, 0, 0)); + put(COMMAND, new Color(255, 123, 0)); + }}; + private Style defaultStyle; private JTextPane outputArea; @@ -46,10 +57,8 @@ public class BotLog { //Define each type's color. for (TYPE type : TYPE.values()) { this.logStyles.put(type, outputArea.addStyle(type.name(), this.defaultStyle)); + this.logStyles.get(type).addAttribute(StyleConstants.Foreground, logStyleColors.get(type)); } - this.logStyles.get(INFO).addAttribute(StyleConstants.Foreground, Color.blue); - this.logStyles.get(MUSIC).addAttribute(StyleConstants.Foreground, new Color(51, 175, 66)); - this.logStyles.get(ERROR).addAttribute(StyleConstants.Foreground, Color.red); } /** @@ -70,4 +79,24 @@ public class BotLog { } } + /** + * Writes a string to the output window with the given tag, guild name, and text. + * @param type The type of message to write. + * @param guild The guild to get the name of. + * @param message The content of the message. + */ + public void log(TYPE type, IGuild guild, String message){ + Date date = new Date(System.currentTimeMillis()); + DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS"); + String dateFormatted = formatter.format(date); + try { + this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle); + this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+type.name()+']', this.logStyles.get(type)); + this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+guild.getName()+"] ", this.defaultStyle); + this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), message+'\n', this.defaultStyle); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } diff --git a/src/main/java/handiebot/view/View.form b/src/main/java/handiebot/view/View.form index 2a4288f..41da417 100644 --- a/src/main/java/handiebot/view/View.form +++ b/src/main/java/handiebot/view/View.form @@ -43,7 +43,11 @@ - + + + + +