diff --git a/src/main/java/handiebot/HandieBot.java b/src/main/java/handiebot/HandieBot.java index 274ccce..ae486ec 100644 --- a/src/main/java/handiebot/HandieBot.java +++ b/src/main/java/handiebot/HandieBot.java @@ -1,24 +1,16 @@ package handiebot; -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.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 handiebot.lavaplayer.GuildMusicManager; +import handiebot.lavaplayer.MusicPlayer; import sx.blah.discord.api.ClientBuilder; import sx.blah.discord.api.IDiscordClient; import sx.blah.discord.api.events.EventSubscriber; -import sx.blah.discord.handle.audio.IAudioManager; import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; -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.DiscordException; -import sx.blah.discord.util.MissingPermissionsException; import sx.blah.discord.util.RateLimitException; import java.util.HashMap; @@ -45,6 +37,7 @@ public class HandieBot { private final AudioPlayerManager playerManager; private final Map musicManagers; + private MusicPlayer musicPlayer; private HandieBot() { this.musicManagers = new HashMap<>(); @@ -53,20 +46,11 @@ public class HandieBot { AudioSourceManagers.registerLocalSource(playerManager); this.commandHandler = new CommandHandler(this); + this.musicPlayer = new MusicPlayer(); } - private synchronized GuildMusicManager getGuildAudioPlayer(IGuild guild) { - long guildId = Long.parseLong(guild.getID()); - GuildMusicManager musicManager = musicManagers.get(guildId); - - if (musicManager == null) { - musicManager = new GuildMusicManager(playerManager); - musicManagers.put(guildId, musicManager); - } - - guild.getAudioManager().setAudioProvider(musicManager.getAudioProvider()); - - return musicManager; + public MusicPlayer getMusicPlayer(){ + return this.musicPlayer; } @EventSubscriber @@ -74,76 +58,5 @@ public class HandieBot { this.commandHandler.handleCommand(event); } - public void loadAndPlay(final IChannel channel, final String trackUrl) { - GuildMusicManager musicManager = getGuildAudioPlayer(channel.getGuild()); - playerManager.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler() { - @Override - public void trackLoaded(AudioTrack track) { - sendMessageToChannel(channel, "Adding to queue " + track.getInfo().title); - - play(channel.getGuild(), musicManager, track); - } - - @Override - public void playlistLoaded(AudioPlaylist playlist) { - AudioTrack firstTrack = playlist.getSelectedTrack(); - - if (firstTrack == null) { - firstTrack = playlist.getTracks().get(0); - } - - sendMessageToChannel(channel, "Adding to queue " + firstTrack.getInfo().title + " (first track of playlist " + playlist.getName() + ")"); - - play(channel.getGuild(), musicManager, firstTrack); - } - - @Override - public void noMatches() { - sendMessageToChannel(channel, "Nothing found by " + trackUrl); - } - - @Override - public void loadFailed(FriendlyException exception) { - sendMessageToChannel(channel, "Could not play: " + exception.getMessage()); - } - }); - } - - private void play(IGuild guild, GuildMusicManager musicManager, AudioTrack track) { - connectToFirstVoiceChannel(guild.getAudioManager()); - - musicManager.scheduler.queue(track); - } - - public void skipTrack(IChannel channel) { - GuildMusicManager musicManager = getGuildAudioPlayer(channel.getGuild()); - musicManager.scheduler.nextTrack(); - - sendMessageToChannel(channel, "Skipped to next track."); - } - - private void sendMessageToChannel(IChannel channel, String message) { - try { - channel.sendMessage(message); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static void connectToFirstVoiceChannel(IAudioManager audioManager) { - for (IVoiceChannel voiceChannel : audioManager.getGuild().getVoiceChannels()) { - if (voiceChannel.isConnected()) { - return; - } - } - - for (IVoiceChannel voiceChannel : audioManager.getGuild().getVoiceChannels()) { - try { - voiceChannel.join(); - } catch (MissingPermissionsException e) { - e.printStackTrace(); - } - } - } } diff --git a/src/main/java/handiebot/command/CommandHandler.java b/src/main/java/handiebot/command/CommandHandler.java index 9a8a36b..58e0113 100644 --- a/src/main/java/handiebot/command/CommandHandler.java +++ b/src/main/java/handiebot/command/CommandHandler.java @@ -35,9 +35,13 @@ public class CommandHandler { String[] args = extractArgs(message); if (guild != null && command != null){ if (command.equals("play") && args.length == 1){ - this.bot.loadAndPlay(channel, args[0]); + this.bot.getMusicPlayer().loadToQueue(guild, args[0]); + } else if (command.equals("skip") && args.length == 0){ + this.bot.getMusicPlayer().skipTrack(guild); } else if (command.equals("help")){ this.sendHelpInfo(user); + } else if (command.equals("playnow") && args.length == 1){ + } } } diff --git a/src/main/java/handiebot/lavaplayer/MusicPlayer.java b/src/main/java/handiebot/lavaplayer/MusicPlayer.java new file mode 100644 index 0000000..ef70a9a --- /dev/null +++ b/src/main/java/handiebot/lavaplayer/MusicPlayer.java @@ -0,0 +1,145 @@ +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.source.AudioSourceManagers; +import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; +import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import sx.blah.discord.handle.obj.IChannel; +import sx.blah.discord.handle.obj.IGuild; +import sx.blah.discord.handle.obj.IVoiceChannel; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Andrew Lalis + * This class is a container for all the music related functions, and contains methods for easy playback and queue + * management. + */ +public class MusicPlayer { + + private static String CHANNEL_NAME = "music"; + + private final AudioPlayerManager playerManager; + private final Map musicManagers; + + public MusicPlayer(){ + this.musicManagers = new HashMap<>(); + this.playerManager = new DefaultAudioPlayerManager(); + AudioSourceManagers.registerLocalSource(playerManager); + AudioSourceManagers.registerRemoteSources(playerManager); + } + + /** + * Loads a URL to the queue, or outputs an error message if it fails. + * @param guild The guild to load the URL to. + * @param trackURL A string representing a youtube/soundcloud URL. + */ + public void loadToQueue(IGuild guild, String trackURL){ + GuildMusicManager musicManager = this.getGuildMusicManager(guild); + this.playerManager.loadItemOrdered(musicManager, trackURL, new AudioLoadResultHandler() { + @Override + public void trackLoaded(AudioTrack audioTrack) { + addToQueue(guild, musicManager, audioTrack); + } + + @Override + public void playlistLoaded(AudioPlaylist audioPlaylist) { + if (audioPlaylist.getTracks().size() > 0){ + AudioTrack firstTrack = audioPlaylist.getSelectedTrack(); + if (firstTrack == null){ + firstTrack = audioPlaylist.getTracks().get(0); + } + addToQueue(guild, musicManager,firstTrack); + } + } + + @Override + public void noMatches() { + getMessageChannel(guild).sendMessage("Unable to find a result for: "+trackURL); + } + + @Override + public void loadFailed(FriendlyException e) { + getMessageChannel(guild).sendMessage("Unable to load. "+e.getMessage()); + } + }); + } + + /** + * Adds a track to the queue and sends a message to the appropriate channel notifying users. + * @param guild The guild to queue the track in. + * @param musicManager The music manager to use. + * @param track The track to queue. + */ + public void addToQueue(IGuild guild, GuildMusicManager musicManager, AudioTrack track){ + IVoiceChannel voiceChannel = this.connectToMusicChannel(guild); + if (voiceChannel != null){ + musicManager.scheduler.queue(track); + IChannel channel = this.getMessageChannel(guild); + channel.sendMessage("Added ["+track.getInfo().title+"] to the queue."); + } + + } + + /** + * Skips the current track. + * @param guild The guild to perform the skip on. + */ + public void skipTrack(IGuild guild){ + this.getGuildMusicManager(guild).scheduler.nextTrack(); + this.getMessageChannel(guild).sendMessage("Skipping the current track."); + } + + /** + * Gets or creates a music manager for a specific guild. + * @param guild The guild to get a manager for. + * @return A Music Manager for the guild. + */ + private synchronized GuildMusicManager getGuildMusicManager(IGuild guild){ + long guildId = Long.parseLong(guild.getStringID()); + GuildMusicManager musicManager = this.musicManagers.get(guildId); + if (musicManager == null){ + musicManager = new GuildMusicManager(this.playerManager); + musicManagers.put(guildId, musicManager); + } + guild.getAudioManager().setAudioProvider(musicManager.getAudioProvider()); + return musicManager; + } + + /** + * Searches for and attempts to connect to a channel called 'music'. + * @param guild the guild to get voice channels from. + * @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; + } + } + IVoiceChannel voiceChannel = guild.createVoiceChannel(CHANNEL_NAME); + voiceChannel.join(); + return voiceChannel; + } + + /** + * Returns a 'music' message channel where the bot can post info on playing songs, user requests, + * etc. + * @param guild The guild to get channels from. + * @return The channel with that name. + */ + private IChannel getMessageChannel(IGuild guild){ + List channels = guild.getChannelsByName(CHANNEL_NAME); + if (channels.size() == 1){ + return channels.get(0); + } + return guild.createChannel(CHANNEL_NAME); + } + +}