diff --git a/pom.xml b/pom.xml index 5ceabfe..21b6797 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,10 @@ jar + + 1.1.0 + + jcenter @@ -43,6 +47,11 @@ lavaplayer 1.2.39 + + com.github.kennedyoliveira + pastebin4j + ${pastebin4j.version} + \ No newline at end of file diff --git a/src/main/java/handiebot/HandieBot.java b/src/main/java/handiebot/HandieBot.java index ec09d16..b285951 100644 --- a/src/main/java/handiebot/HandieBot.java +++ b/src/main/java/handiebot/HandieBot.java @@ -8,6 +8,7 @@ import handiebot.view.View; import sx.blah.discord.api.ClientBuilder; import sx.blah.discord.api.IDiscordClient; import sx.blah.discord.api.events.EventSubscriber; +import sx.blah.discord.handle.impl.events.ReadyEvent; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.RateLimitException; @@ -26,17 +27,17 @@ public class HandieBot { private static BotWindow window; public static BotLog log; - private CommandHandler commandHandler; + private static CommandHandler commandHandler; public static MusicPlayer musicPlayer; - private HandieBot() { - this.commandHandler = new CommandHandler(this); - - } - @EventSubscriber public void onMessageReceived(MessageReceivedEvent event) { - this.commandHandler.handleCommand(event); + commandHandler.handleCommand(event); + } + + @EventSubscriber + public void onReady(ReadyEvent event){ + log.log(BotLog.TYPE.INFO, "HandieBot initialized."); } public static void main(String[] args) throws DiscordException, RateLimitException { @@ -47,7 +48,7 @@ public class HandieBot { log = new BotLog(view.getOutputArea()); window = new BotWindow(view); - log.log(BotLog.TYPE.INFO, "Logging client in."); + log.log(BotLog.TYPE.INFO, "Logging client in..."); client = new ClientBuilder().withToken(TOKEN).build(); client.getDispatcher().registerListener(new HandieBot()); client.login(); diff --git a/src/main/java/handiebot/command/CommandHandler.java b/src/main/java/handiebot/command/CommandHandler.java index 1b2b0d2..642682a 100644 --- a/src/main/java/handiebot/command/CommandHandler.java +++ b/src/main/java/handiebot/command/CommandHandler.java @@ -1,14 +1,21 @@ package handiebot.command; import com.sun.istack.internal.NotNull; -import handiebot.HandieBot; import handiebot.utils.DisappearingMessage; +import handiebot.view.BotLog; +import handiebot.view.actions.QuitAction; +import handiebot.view.actions.music.PlayAction; +import handiebot.view.actions.music.QueueListAction; +import handiebot.view.actions.music.SkipAction; +import handiebot.view.actions.music.ToggleRepeatAction; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; import sx.blah.discord.handle.obj.*; import sx.blah.discord.util.EmbedBuilder; import java.awt.*; +import static handiebot.HandieBot.log; + /** * @author Andrew Lalis * Class to process commands. @@ -16,18 +23,11 @@ import java.awt.*; public class CommandHandler { public static String PREFIX = "!"; - - private final HandieBot bot; - - public CommandHandler(HandieBot bot){ - this.bot = bot; - } - /** * Main method to handle user messages. * @param event The event generated by the message. */ - public void handleCommand(MessageReceivedEvent event){ + public static void handleCommand(MessageReceivedEvent event){ IMessage message = event.getMessage(); IUser user = event.getAuthor(); IChannel channel = event.getChannel(); @@ -38,29 +38,24 @@ public class CommandHandler { DisappearingMessage.deleteMessageAfter(1000, message); if (command.equals("play")){ //Play or queue a song. - if (args.length == 1) { - HandieBot.musicPlayer.loadToQueue(guild, args[0]); - } else if (args.length == 0){ - HandieBot.musicPlayer.playQueue(guild); - } + new PlayAction(guild, args).actionPerformed(null); } else if (command.equals("skip") && args.length == 0){ //Skip the current song. - HandieBot.musicPlayer.skipTrack(guild); + new SkipAction(guild).actionPerformed(null); } 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){ + sendHelpInfo(user);//TODO finish the help command and fill in with new descriptions each time. + } else if (command.equals("queue")){ //Display the first few items of the queue. - HandieBot.musicPlayer.showQueueList(guild); + new QueueListAction(guild, (args.length == 1) && args[0].equals("all")).actionPerformed(null); } else if (command.equals("repeat")){ //Toggle repeat. - HandieBot.musicPlayer.toggleRepeat(guild); + new ToggleRepeatAction(guild).actionPerformed(null); } else if (command.equals("clear")){ //TODO clear command. } else if (command.equals("quit")){ //Quit the application. - channel.sendMessage("Quitting HandieBot functions."); - HandieBot.musicPlayer.quit(guild); + new QuitAction(guild).actionPerformed(null); } else if (command.equals("playlist")){ //Do playlist actions. //TODO perform actions! @@ -69,8 +64,12 @@ public class CommandHandler { if (args[0].length() != 1){ new DisappearingMessage(channel, "You may only set the prefix to 1 character. To do otherwise is simply foolish.", 3000); } else { + new DisappearingMessage(channel, "Command prefix set to "+PREFIX, 10000); + log.log(BotLog.TYPE.INFO, guild, "Prefix set to "+PREFIX); setPrefix(args[0]); } + } else { + log.log(BotLog.TYPE.ERROR, guild, "Invalid command: "+command+" issued by "+user.getName()); } } } @@ -80,7 +79,7 @@ public class CommandHandler { * @param message The message to get a command from. * @return The command word, minus the prefix, or null. */ - private String extractCommand(IMessage message){ + private static String extractCommand(IMessage message){ String[] words = message.getContent().split(" "); if (words[0].startsWith(PREFIX)){ return words[0].replaceFirst(PREFIX, "").toLowerCase(); @@ -94,7 +93,7 @@ public class CommandHandler { * @return A list of strings representing args. */ @NotNull - private String[] extractArgs(IMessage message){ + private static String[] extractArgs(IMessage message){ String[] words = message.getContent().split(" "); if (words[0].startsWith(PREFIX)){ String[] args = new String[words.length-1]; @@ -110,7 +109,7 @@ public class CommandHandler { * Method to send a useful list of commands to any user if they desire. * @param user The user to send the message to. */ - private void sendHelpInfo(IUser user){ + private static void sendHelpInfo(IUser user){ IPrivateChannel pm = user.getOrCreatePMChannel(); EmbedBuilder builder = new EmbedBuilder(); diff --git a/src/main/java/handiebot/lavaplayer/MusicPlayer.java b/src/main/java/handiebot/lavaplayer/MusicPlayer.java index e4ffb5d..79296f6 100644 --- a/src/main/java/handiebot/lavaplayer/MusicPlayer.java +++ b/src/main/java/handiebot/lavaplayer/MusicPlayer.java @@ -31,7 +31,8 @@ import static handiebot.HandieBot.log; public class MusicPlayer { //Name for the message and voice channels dedicated to this bot. - public static String CHANNEL_NAME = "HandieBotMusic"; + static String CHANNEL_NAME = "HandieBotMusic"; + private static String PASTEBIN_KEY = "769adc01154922ece448cabd7a33b57c"; private final AudioPlayerManager playerManager; @@ -74,7 +75,7 @@ public class MusicPlayer { * @param guild The guild to get the channel from. * @return A message channel on a particular guild that is specifically for music. */ - private IChannel getChatChannel(IGuild guild){ + public IChannel getChatChannel(IGuild guild){ if (!this.chatChannels.containsKey(guild)){ List channels = guild.getChannelsByName(CHANNEL_NAME.toLowerCase()); if (channels.isEmpty()){ @@ -93,7 +94,7 @@ public class MusicPlayer { * @param guild The guild to get the channel from. * @return The voice channel on a guild that is for this bot. */ - private IVoiceChannel getVoiceChannel(IGuild guild){ + public IVoiceChannel getVoiceChannel(IGuild guild){ if (!this.voiceChannels.containsKey(guild)){ List channels = guild.getVoiceChannelsByName(CHANNEL_NAME); if (channels.isEmpty()){ @@ -119,32 +120,56 @@ public class MusicPlayer { /** * Sends a formatted message to the guild about the first few items in a queue. */ - public void showQueueList(IGuild guild){ + public void showQueueList(IGuild guild, boolean showAll){ List tracks = getMusicManager(guild).scheduler.queueList(); if (tracks.size() == 0) { new DisappearingMessage(getChatChannel(guild), "The queue is empty. Use **"+ CommandHandler.PREFIX+"play** *URL* to add songs.", 3000); } 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; - seconds = seconds % 60; - String time = String.format(" [%d:%02d]\n", minutes, seconds); - sb.append(time); + if (!showAll) { + 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; + 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); + IMessage message = getChatChannel(guild).sendMessage(builder.build()); + DisappearingMessage.deleteMessageAfter(6000, message); + } else { + StringBuilder sb = new StringBuilder("Queue for Discord Server: "+guild.getName()+"\n"); + for (int i = 0; i < tracks.size(); i++){ + sb.append(i+1).append(". ").append(tracks.get(i).getInfo().title); + int seconds = (int) (tracks.get(i).getInfo().length / 1000); + int minutes = seconds / 60; + seconds = seconds % 60; + String time = String.format(" [%d:%02d]\n", minutes, seconds); + sb.append(time); + } + //TODO: get pastebin working. + /* + PasteBin pasteBin = new PasteBin(new AccountCredentials(PASTEBIN_KEY)); + Paste paste = new Paste(PASTEBIN_KEY); + paste.setTitle("Music Queue for Discord Server: "+guild.getName()); + paste.setContent(sb.toString()); + paste.setExpiration(PasteExpiration.ONE_HOUR); + paste.setVisibility(PasteVisibility.PUBLIC); + final String pasteURL = pasteBin.createPaste(paste); + log.log(BotLog.TYPE.INFO, guild, "Uploaded full queue to "+pasteURL); + new DisappearingMessage(getChatChannel(guild), "You may view the full queue here. "+pasteURL, 60000); + */ } - builder.withTimestamp(System.currentTimeMillis()); - builder.appendField("Showing " + (tracks.size() <= 10 ? tracks.size() : "the first 10") + " track"+(tracks.size() > 1 ? "s" : "")+".", sb.toString(), false); - IMessage message = getChatChannel(guild).sendMessage(builder.build()); - DisappearingMessage.deleteMessageAfter(6000, message); } } @@ -188,7 +213,7 @@ public class MusicPlayer { * Adds a track to the queue and sends a message to the appropriate channel notifying users. * @param track The track to queue. */ - public void addToQueue(IGuild guild, AudioTrack track){ + private void addToQueue(IGuild guild, AudioTrack track){ IVoiceChannel voiceChannel = getVoiceChannel(guild); if (voiceChannel != null){ if (!voiceChannel.isConnected()) { @@ -240,10 +265,6 @@ public class MusicPlayer { */ public void quit(IGuild guild){ getMusicManager(guild).scheduler.quit(); - IVoiceChannel vc = this.getVoiceChannel(guild); - if (vc.isConnected()){ - vc.leave(); - } } /** @@ -252,10 +273,6 @@ public class MusicPlayer { public void quitAll(){ this.musicManagers.forEach((guild, musicManager) -> { musicManager.scheduler.quit(); - IVoiceChannel vc = this.getVoiceChannel(guild); - if (vc.isConnected()){ - vc.leave(); - } }); this.playerManager.shutdown(); } diff --git a/src/main/java/handiebot/lavaplayer/TrackScheduler.java b/src/main/java/handiebot/lavaplayer/TrackScheduler.java index 6e42fdd..30d6d6b 100644 --- a/src/main/java/handiebot/lavaplayer/TrackScheduler.java +++ b/src/main/java/handiebot/lavaplayer/TrackScheduler.java @@ -6,10 +6,12 @@ import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter; import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; +import handiebot.HandieBot; import handiebot.view.BotLog; import sx.blah.discord.handle.obj.IChannel; import sx.blah.discord.handle.obj.IGuild; import sx.blah.discord.handle.obj.IMessage; +import sx.blah.discord.handle.obj.IVoiceChannel; import sx.blah.discord.util.RequestBuffer; import java.util.List; @@ -113,11 +115,19 @@ public class TrackScheduler extends AudioEventAdapter { * Starts the next track, stopping the current one if it's playing. */ public void nextTrack(){ + AudioTrack currentTrack = this.player.getPlayingTrack(); + if (currentTrack != null){ + this.player.stopTrack(); + } AudioTrack track = (this.repeat ? this.activePlaylist.getNextTrackAndRequeue(this.shuffle) : this.activePlaylist.getNextTrackAndRemove(this.shuffle)); if (track != null) { + IVoiceChannel voiceChannel = HandieBot.musicPlayer.getVoiceChannel(this.guild); + if (!voiceChannel.isConnected()){ + voiceChannel.join(); + } player.startTrack(track, false); } else { - player.stopTrack(); + this.quit(); } } @@ -125,8 +135,11 @@ public class TrackScheduler extends AudioEventAdapter { * If the user wishes to quit, stop the currently played track. */ public void quit(){ + IVoiceChannel voiceChannel = HandieBot.musicPlayer.getVoiceChannel(this.guild); + if (voiceChannel.isConnected()){ + voiceChannel.leave(); + } this.player.stopTrack(); - this.player.destroy(); } @Override @@ -134,7 +147,7 @@ public class TrackScheduler extends AudioEventAdapter { 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+"**."); + IMessage message = channels.get(0).sendMessage("Now playing: **"+track.getInfo().title+"**\n"+track.getInfo().uri); RequestBuffer.request(() -> {message.addReaction(":thumbsup:");}).get(); RequestBuffer.request(() -> {message.addReaction(":thumbsdown:");}); } @@ -142,13 +155,10 @@ public class TrackScheduler extends AudioEventAdapter { @Override public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { - System.out.println("Track ended."); if (endReason.mayStartNext){ - System.out.println("Moving to next track."); nextTrack(); } else { - log.log(BotLog.TYPE.ERROR, this.guild, "Unable to go to the next track. Reason: "+endReason.name()); - System.out.println(endReason.toString()); + log.log(BotLog.TYPE.MUSIC, this.guild, "Unable to go to the next track. Reason: "+endReason.name()); } } diff --git a/src/main/java/handiebot/view/CommandLineListener.java b/src/main/java/handiebot/view/CommandLineListener.java index 56fcc4c..0179497 100644 --- a/src/main/java/handiebot/view/CommandLineListener.java +++ b/src/main/java/handiebot/view/CommandLineListener.java @@ -21,6 +21,7 @@ public class CommandLineListener implements KeyListener { //user wishes to submit command. JTextField commandLine = (JTextField) e.getSource(); String[] words = commandLine.getText().trim().split(" "); + commandLine.setText(null); String command = words[0]; String[] args = new String[words.length-1]; for (int i = 1; i < words.length; i++) { diff --git a/src/main/java/handiebot/view/actions/QuitAction.java b/src/main/java/handiebot/view/actions/QuitAction.java index 267d522..23d9089 100644 --- a/src/main/java/handiebot/view/actions/QuitAction.java +++ b/src/main/java/handiebot/view/actions/QuitAction.java @@ -1,6 +1,7 @@ package handiebot.view.actions; import handiebot.HandieBot; +import sx.blah.discord.handle.obj.IGuild; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -10,8 +11,22 @@ import java.awt.event.ActionListener; */ public class QuitAction implements ActionListener { + private IGuild guild; + + public QuitAction(){ + } + + public QuitAction(IGuild guild){ + this.guild = guild; + } + @Override public void actionPerformed(ActionEvent e) { - HandieBot.quit(); + if (guild != null){ + HandieBot.musicPlayer.getChatChannel(this.guild).sendMessage("Quiting HandieBot"); + HandieBot.musicPlayer.quit(this.guild); + } else { + HandieBot.quit(); + } } } diff --git a/src/main/java/handiebot/view/actions/music/MusicAction.java b/src/main/java/handiebot/view/actions/music/MusicAction.java new file mode 100644 index 0000000..14b2e32 --- /dev/null +++ b/src/main/java/handiebot/view/actions/music/MusicAction.java @@ -0,0 +1,18 @@ +package handiebot.view.actions.music; + +import sx.blah.discord.handle.obj.IGuild; + +import java.awt.event.ActionListener; + +/** + * @author Andrew Lalis + */ +public abstract class MusicAction implements ActionListener { + + protected IGuild guild; + + public MusicAction(IGuild guild) { + this.guild = guild; + } + +} diff --git a/src/main/java/handiebot/view/actions/music/PlayAction.java b/src/main/java/handiebot/view/actions/music/PlayAction.java new file mode 100644 index 0000000..a0cdc9b --- /dev/null +++ b/src/main/java/handiebot/view/actions/music/PlayAction.java @@ -0,0 +1,32 @@ +package handiebot.view.actions.music; + +import handiebot.HandieBot; +import sx.blah.discord.handle.obj.IGuild; + +import java.awt.event.ActionEvent; + +/** + * @author Andrew Lalis + */ +public class PlayAction extends MusicAction { + + private String[] args = null; + + public PlayAction(IGuild guild) { + super(guild); + } + + public PlayAction(IGuild guild, String[] args){ + super(guild); + this.args = args; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (this.args == null || this.args.length < 1){ + HandieBot.musicPlayer.playQueue(this.guild); + } else { + HandieBot.musicPlayer.loadToQueue(this.guild, this.args[0]); + } + } +} diff --git a/src/main/java/handiebot/view/actions/music/QueueListAction.java b/src/main/java/handiebot/view/actions/music/QueueListAction.java new file mode 100644 index 0000000..7e53e87 --- /dev/null +++ b/src/main/java/handiebot/view/actions/music/QueueListAction.java @@ -0,0 +1,24 @@ +package handiebot.view.actions.music; + +import handiebot.HandieBot; +import sx.blah.discord.handle.obj.IGuild; + +import java.awt.event.ActionEvent; + +/** + * @author Andrew Lalis + */ +public class QueueListAction extends MusicAction { + + private boolean showAll = false; + + public QueueListAction(IGuild guild, boolean showAll){ + super(guild); + this.showAll = showAll; + } + + @Override + public void actionPerformed(ActionEvent e) { + HandieBot.musicPlayer.showQueueList(this.guild, this.showAll); + } +} diff --git a/src/main/java/handiebot/view/actions/music/SkipAction.java b/src/main/java/handiebot/view/actions/music/SkipAction.java new file mode 100644 index 0000000..f7b3b57 --- /dev/null +++ b/src/main/java/handiebot/view/actions/music/SkipAction.java @@ -0,0 +1,21 @@ +package handiebot.view.actions.music; + +import handiebot.HandieBot; +import sx.blah.discord.handle.obj.IGuild; + +import java.awt.event.ActionEvent; + +/** + * @author Andrew Lalis + */ +public class SkipAction extends MusicAction { + + public SkipAction(IGuild guild) { + super(guild); + } + + @Override + public void actionPerformed(ActionEvent e) { + HandieBot.musicPlayer.skipTrack(this.guild); + } +} diff --git a/src/main/java/handiebot/view/actions/music/ToggleRepeatAction.java b/src/main/java/handiebot/view/actions/music/ToggleRepeatAction.java new file mode 100644 index 0000000..64ded13 --- /dev/null +++ b/src/main/java/handiebot/view/actions/music/ToggleRepeatAction.java @@ -0,0 +1,21 @@ +package handiebot.view.actions.music; + +import handiebot.HandieBot; +import sx.blah.discord.handle.obj.IGuild; + +import java.awt.event.ActionEvent; + +/** + * @author Andrew Lalis + */ +public class ToggleRepeatAction extends MusicAction { + + public ToggleRepeatAction(IGuild guild) { + super(guild); + } + + @Override + public void actionPerformed(ActionEvent e) { + HandieBot.musicPlayer.toggleRepeat(this.guild); + } +}