diff --git a/src/main/java/com/fpghoti/biscuit/Main.java b/src/main/java/com/fpghoti/biscuit/Main.java index d124d57..f17f305 100644 --- a/src/main/java/com/fpghoti/biscuit/Main.java +++ b/src/main/java/com/fpghoti/biscuit/Main.java @@ -13,34 +13,42 @@ import com.fpghoti.biscuit.commands.CommandManager; import com.fpghoti.biscuit.commands.client.AddCommand; import com.fpghoti.biscuit.commands.client.ChanIDCommand; import com.fpghoti.biscuit.commands.client.DivideCommand; -import com.fpghoti.biscuit.commands.client.ForceSkipCommand; import com.fpghoti.biscuit.commands.client.GetConfigCommand; import com.fpghoti.biscuit.commands.client.GuildIDCommand; import com.fpghoti.biscuit.commands.client.ToggleRoleCommand; import com.fpghoti.biscuit.commands.client.HelpCommand; -import com.fpghoti.biscuit.commands.client.LoopMusicCommand; import com.fpghoti.biscuit.commands.client.MultiplyCommand; import com.fpghoti.biscuit.commands.client.NotSpammerCommand; -import com.fpghoti.biscuit.commands.client.NowPlayingCommand; -import com.fpghoti.biscuit.commands.client.PauseCommand; -import com.fpghoti.biscuit.commands.client.TogglePauseCommand; import com.fpghoti.biscuit.commands.client.MakeInviteCommand; import com.fpghoti.biscuit.commands.client.PingCommand; -import com.fpghoti.biscuit.commands.client.PlayCommand; -import com.fpghoti.biscuit.commands.client.PlayFirstCommand; import com.fpghoti.biscuit.commands.client.PowerCommand; -import com.fpghoti.biscuit.commands.client.QueueCommand; import com.fpghoti.biscuit.commands.client.RecentSpammersCommand; import com.fpghoti.biscuit.commands.client.SaveConfigCommand; -import com.fpghoti.biscuit.commands.client.SkipCommand; import com.fpghoti.biscuit.commands.client.SoftMuteCommand; import com.fpghoti.biscuit.commands.client.SquareRootCommand; import com.fpghoti.biscuit.commands.client.SubtractCommand; import com.fpghoti.biscuit.commands.client.UIDCommand; import com.fpghoti.biscuit.commands.client.UnSoftMuteCommand; -import com.fpghoti.biscuit.commands.client.UnpauseCommand; import com.fpghoti.biscuit.commands.client.WikiCommand; -import com.fpghoti.biscuit.commands.client.WipeQueueCommand; +import com.fpghoti.biscuit.commands.client.music.ClearCommand; +import com.fpghoti.biscuit.commands.client.music.ForceSkipCommand; +import com.fpghoti.biscuit.commands.client.music.ForceSkipToCommand; +import com.fpghoti.biscuit.commands.client.music.ClearUserSongsCommand; +import com.fpghoti.biscuit.commands.client.music.LoopMusicCommand; +import com.fpghoti.biscuit.commands.client.music.MoveToCommand; +import com.fpghoti.biscuit.commands.client.music.NowPlayingCommand; +import com.fpghoti.biscuit.commands.client.music.PauseCommand; +import com.fpghoti.biscuit.commands.client.music.PlayCommand; +import com.fpghoti.biscuit.commands.client.music.PlayFirstCommand; +import com.fpghoti.biscuit.commands.client.music.QueueCommand; +import com.fpghoti.biscuit.commands.client.music.RemoveCommand; +import com.fpghoti.biscuit.commands.client.music.ShuffleCommand; +import com.fpghoti.biscuit.commands.client.music.SkipAllCommand; +import com.fpghoti.biscuit.commands.client.music.SkipCommand; +import com.fpghoti.biscuit.commands.client.music.TogglePauseCommand; +import com.fpghoti.biscuit.commands.client.music.UnpauseCommand; +import com.fpghoti.biscuit.commands.client.music.VolumeCommand; +import com.fpghoti.biscuit.commands.client.music.WipeQueueCommand; import com.fpghoti.biscuit.commands.console.GuildSayCommand; import com.fpghoti.biscuit.commands.console.SayCommand; import com.fpghoti.biscuit.commands.console.ShutdownConsoleCommand; @@ -151,6 +159,9 @@ public class Main { CommandManager.addCommand(new SaveConfigCommand()); CommandManager.addCommand(new GuildIDCommand()); CommandManager.addCommand(new WikiCommand()); + + //Music Client + CommandManager.addCommand(new PlayCommand()); CommandManager.addCommand(new PlayFirstCommand()); CommandManager.addCommand(new ForceSkipCommand()); @@ -162,6 +173,14 @@ public class Main { CommandManager.addCommand(new NowPlayingCommand()); CommandManager.addCommand(new WipeQueueCommand()); CommandManager.addCommand(new LoopMusicCommand()); + CommandManager.addCommand(new VolumeCommand()); + CommandManager.addCommand(new ShuffleCommand()); + CommandManager.addCommand(new RemoveCommand()); + CommandManager.addCommand(new ClearCommand()); + CommandManager.addCommand(new MoveToCommand()); + CommandManager.addCommand(new ForceSkipToCommand()); + CommandManager.addCommand(new ClearUserSongsCommand()); + CommandManager.addCommand(new SkipAllCommand()); //Console diff --git a/src/main/java/com/fpghoti/biscuit/audio/AudioResultHandler.java b/src/main/java/com/fpghoti/biscuit/audio/AudioResultHandler.java deleted file mode 100644 index 255cbca..0000000 --- a/src/main/java/com/fpghoti/biscuit/audio/AudioResultHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fpghoti.biscuit.audio; - -import com.fpghoti.biscuit.Main; -import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.rest.MessageText; -import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; -import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; -import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; -import com.sedmelluq.discord.lavaplayer.track.AudioTrack; - -import net.dv8tion.jda.api.entities.TextChannel; - -public class AudioResultHandler implements AudioLoadResultHandler { - - private Biscuit biscuit; - private String uid; - private TextChannel channel; - private String searchPhrase; - private boolean search; - private boolean first; - private boolean playAfterQueue; - - public AudioResultHandler(String uid, TextChannel channel, boolean search, String searchPhrase, boolean first, boolean playAfterQueue) { - this.biscuit = Biscuit.getBiscuit(channel.getGuild()); - this.uid = uid; - this.channel = channel; - this.search = search; - this.searchPhrase = searchPhrase; - this.first = first; - this.playAfterQueue = playAfterQueue; - } - - @Override - public void trackLoaded(AudioTrack track) { - if(first) { - biscuit.getAudioScheduler().queue(track, uid, channel, 1); - }else { - biscuit.getAudioScheduler().queue(track, uid, channel); - } - if(playAfterQueue) { - biscuit.getAudioScheduler().startPlaying(); - } - } - - @Override - public void playlistLoaded(AudioPlaylist playlist) { - AudioTrack track = playlist.getTracks().get(0); - if(first) { - biscuit.getAudioScheduler().queue(track, uid, channel, 1); - }else { - biscuit.getAudioScheduler().queue(track, uid, channel); - } - if(playAfterQueue) { - biscuit.getAudioScheduler().startPlaying(); - } - } - - @Override - public void noMatches() { - if(!search) { - biscuit.log("Exact match not found. Searching instead..."); - Main.getPlayerManager().loadItemOrdered(biscuit.getGuild(),"ytsearch:" + searchPhrase, new AudioResultHandler(uid, channel, true, searchPhrase, first, false)); - }else { - MessageText.send(channel, "Song match not found."); - } - } - - @Override - public void loadFailed(FriendlyException exception) { - exception.printStackTrace(); - MessageText.send(channel, "An error was encountered while attempting to load audio."); - } - - - -} diff --git a/src/main/java/com/fpghoti/biscuit/audio/AudioScheduler.java b/src/main/java/com/fpghoti/biscuit/audio/AudioScheduler.java index eece3d6..94173ca 100644 --- a/src/main/java/com/fpghoti/biscuit/audio/AudioScheduler.java +++ b/src/main/java/com/fpghoti/biscuit/audio/AudioScheduler.java @@ -5,6 +5,9 @@ import java.util.ArrayList; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.audio.queue.AudioQueue; import com.fpghoti.biscuit.audio.queue.QueuedTrack; +import com.fpghoti.biscuit.audio.request.youtube.YTImmediateRequest; +import com.fpghoti.biscuit.audio.request.youtube.YTRequest; +import com.fpghoti.biscuit.audio.result.YTResultHandler; import com.fpghoti.biscuit.biscuit.Biscuit; import com.fpghoti.biscuit.rest.MessageText; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; @@ -13,6 +16,7 @@ import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; +import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.TextChannel; public class AudioScheduler extends AudioEventAdapter { @@ -59,7 +63,8 @@ public class AudioScheduler extends AudioEventAdapter { TextChannel channel = qt.getCommandChannel(); MessageText.send(channel, "The video selected cannot be played through the music player. An alternate track will be played if available."); title = title.toLowerCase().replace("vevo", "") + " lyrics"; - Main.getPlayerManager().loadItemOrdered(biscuit.getGuild(),"ytsearch:" + title, new AudioResultHandler(qt.getUserId(), channel, true, title, true, !queue.isEmpty())); + YTRequest request = new YTImmediateRequest(channel, qt.getUserId(), title); + Main.getPlayerManager().loadItemOrdered(biscuit.getGuild(),"ytsearch:" + title, new YTResultHandler(request)); return; } break; @@ -133,6 +138,7 @@ public class AudioScheduler extends AudioEventAdapter { return; } biscuit.getGuild().getAudioManager().closeAudioConnection(); + biscuit.getAudioPlayer().setVolume(100); skips.clear(); return; } @@ -167,9 +173,17 @@ public class AudioScheduler extends AudioEventAdapter { public AudioQueue getQueue(){ return queue; } - + public void skip() { + skip(null); + } + + public void skip(TextChannel channel) { biscuit.getAudioPlayer().stopTrack(); + if(channel != null && queue.getNext() != null ) { + MessageEmbed next = queue.getNext().getEmbedMessage("Now Playing:"); + MessageText.send(channel, next); + } startPlaying(); } diff --git a/src/main/java/com/fpghoti/biscuit/audio/PlayCommandUtil.java b/src/main/java/com/fpghoti/biscuit/audio/PlayCommandUtil.java new file mode 100644 index 0000000..f182dbc --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/PlayCommandUtil.java @@ -0,0 +1,76 @@ +package com.fpghoti.biscuit.audio; + +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.rest.MessageText; + +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.entities.VoiceChannel; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.managers.AudioManager; + +public class PlayCommandUtil { + + public static boolean connectToChannel(GuildMessageReceivedEvent event) { + Guild guild = event.getGuild(); + Biscuit biscuit = Biscuit.getBiscuit(guild); + TextChannel textChannel = event.getChannel(); + + String vcname = ""; + if(!event.getMember().getVoiceState().inVoiceChannel()) { + MessageText.send(textChannel, "You must be in a voice channel to do this!"); + return false; + } + vcname = event.getMember().getVoiceState().getChannel().getName(); + String[] musicChannels = biscuit.getProperties().getMusicChannels(); + if(musicChannels.length >= 1) { + boolean found = false; + for(String cname : musicChannels) { + if(event.getMember().getVoiceState().getChannel().getName().equalsIgnoreCase(cname)) { + found = true; + break; + } + } + if(found == false) { + MessageText.send(textChannel, "You are not in a channel that is authorized to use the music player."); + return false; + } + } + + if(biscuit.getAudioPlayer().getPlayingTrack() != null && guild.getAudioManager().isConnected() && !guild.getAudioManager().getConnectedChannel().getMembers().contains(event.getMember())) { + MessageText.send(textChannel, "Music is already playing in a voice channel. Connect to " + + "that channel, then queue your song."); + return false; + } + + VoiceChannel voiceChannel = guild.getVoiceChannelsByName(vcname, true).get(0); + AudioManager manager = guild.getAudioManager(); + + manager.setSendingHandler(new AudioHandler(biscuit.getAudioPlayer())); + manager.openAudioConnection(voiceChannel); + return true; + } + + public static String getSearchPhrase(String[] args) { + String searchPhrase = args[0]; + if(args.length > 1) { + for(int i = 1; i < args.length; i++) { + searchPhrase = searchPhrase + " " + args[i]; + } + } + return searchPhrase; + } + + public static String getID(GuildMessageReceivedEvent event) { + return getID(event.getMessage().getContentRaw().split(" ")[1]); + } + + public static String getID(String url) { + String[] s = url.split("="); + if(s.length > 1) { + return s[1].split("&")[0]; + } + return url; + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/queue/AudioQueue.java b/src/main/java/com/fpghoti/biscuit/audio/queue/AudioQueue.java index 184254b..b6ffdb6 100644 --- a/src/main/java/com/fpghoti/biscuit/audio/queue/AudioQueue.java +++ b/src/main/java/com/fpghoti/biscuit/audio/queue/AudioQueue.java @@ -1,6 +1,7 @@ package com.fpghoti.biscuit.audio.queue; import java.util.ArrayList; +import java.util.Collections; import com.fpghoti.biscuit.rest.MessageText; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; @@ -19,13 +20,13 @@ public class AudioQueue { } public ArrayList getUserTracks(String userId){ - ArrayList tracks = new ArrayList(); + ArrayList qts = new ArrayList(); for(QueuedTrack qt : tracks) { if(qt.getUserId().equals(userId)) { - tracks.add(qt); + qts.add(qt); } } - return tracks; + return qts; } public void removeUserTracks(String userId) { @@ -33,6 +34,19 @@ public class AudioQueue { tracks.remove(qt); } } + + public void shuffleUserTracks(String userId) { + ArrayList qts = getUserTracks(userId); + Collections.shuffle(qts); + int index = 0; + for(int i = 0; i < tracks.size(); i++) { + QueuedTrack track = tracks.get(i); + if(track.getUserId().equals(userId)) { + tracks.set(i, qts.get(index)); + index++; + } + } + } public void playNext() { QueuedTrack next = tracks.iterator().next(); @@ -129,6 +143,26 @@ public class AudioQueue { tracks.remove(track); return true; } + + //Goes by viewable place rather than index for + //easy implementation into command. + public boolean removeTracksBefore(int place) { + int index = place - 1; + if(index < 1) { + return false; + } + ArrayList trs = new ArrayList(tracks); + int count = 0; + for(QueuedTrack t : trs) { + if(count < index) { + tracks.remove(t); + }else { + return true; + } + count++; + } + return true; + } public QueuedTrack getNext() { if(isEmpty()) { diff --git a/src/main/java/com/fpghoti/biscuit/audio/queue/QueuedTrack.java b/src/main/java/com/fpghoti/biscuit/audio/queue/QueuedTrack.java index b0d9442..2d74b86 100644 --- a/src/main/java/com/fpghoti/biscuit/audio/queue/QueuedTrack.java +++ b/src/main/java/com/fpghoti/biscuit/audio/queue/QueuedTrack.java @@ -62,7 +62,15 @@ public class QueuedTrack { embed.setTitle(title, track.getInfo().uri); embed.setColor(Color.CYAN); - String desc = "Author: " + track.getInfo().author + "\nLength: " + Util.getTime(track.getDuration()); + long duration = track.getDuration(); + + //Duration seems to change after track begins playing + //This is to make the embeds more consistant with each other + if(showRemaining) { + duration+=1000; + } + + String desc = "Author: " + track.getInfo().author + "\nLength: " + Util.getTime(duration); if(showRemaining) { desc = desc + "\nTime Remaining: " + Util.getTime(track.getDuration() - track.getPosition()); diff --git a/src/main/java/com/fpghoti/biscuit/audio/request/PlayRequest.java b/src/main/java/com/fpghoti/biscuit/audio/request/PlayRequest.java new file mode 100644 index 0000000..16408e8 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/request/PlayRequest.java @@ -0,0 +1,44 @@ +package com.fpghoti.biscuit.audio.request; + +import com.fpghoti.biscuit.biscuit.Biscuit; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.TextChannel; + +public abstract class PlayRequest { + + private TextChannel channel; + private Biscuit biscuit; + private String authorId; + private String identifier; + + public PlayRequest(Message message, String identifier) { + this(message.getTextChannel(), message.getAuthor().getId(), identifier); + } + + public PlayRequest(TextChannel channel, String authorId, String identifier) { + this.channel = channel; + this.authorId = authorId; + this.identifier = identifier; + this.biscuit = Biscuit.getBiscuit(channel.getGuild()); + } + + public TextChannel getRequestChannel() { + return channel; + } + + public Biscuit getBiscuit() { + return biscuit; + } + + public String getAuthorId() { + return authorId; + } + + public String getIdentifier() { + return identifier; + } + + public abstract RequestType getType(); + +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/request/RequestType.java b/src/main/java/com/fpghoti/biscuit/audio/request/RequestType.java new file mode 100644 index 0000000..7c68b01 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/request/RequestType.java @@ -0,0 +1,9 @@ +package com.fpghoti.biscuit.audio.request; + +public enum RequestType { + + YOUTUBE, + YOUTUBE_IMMEDIATE, + YOUTUBE_PRIORITY; + +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTImmediateRequest.java b/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTImmediateRequest.java new file mode 100644 index 0000000..8c6507f --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTImmediateRequest.java @@ -0,0 +1,23 @@ +package com.fpghoti.biscuit.audio.request.youtube; + +import com.fpghoti.biscuit.audio.request.RequestType; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.TextChannel; + +public class YTImmediateRequest extends YTRequest{ + + public YTImmediateRequest(Message message, String identifier) { + super(message, identifier); + } + + public YTImmediateRequest(TextChannel channel, String authorId, String identifier) { + super(channel, authorId, identifier); + } + + @Override + public RequestType getType() { + return RequestType.YOUTUBE_IMMEDIATE; + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTPriorityRequest.java b/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTPriorityRequest.java new file mode 100644 index 0000000..487a542 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTPriorityRequest.java @@ -0,0 +1,34 @@ +package com.fpghoti.biscuit.audio.request.youtube; + +import com.fpghoti.biscuit.audio.request.RequestType; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.TextChannel; + +public class YTPriorityRequest extends YTRequest{ + + int insertSlot; + + public YTPriorityRequest(Message message, String identifier, int insertSlot) { + this(message.getTextChannel(), message.getAuthor().getId(), identifier, insertSlot); + } + + public YTPriorityRequest(TextChannel channel, String authorId, String identifier, int insertSlot) { + super(channel, authorId, identifier); + this.insertSlot = insertSlot; + } + + public int getSlot() { + return insertSlot; + } + + public void setSlot(int slotNumber) { + insertSlot = slotNumber; + } + + @Override + public RequestType getType() { + return RequestType.YOUTUBE_PRIORITY; + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTRequest.java b/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTRequest.java new file mode 100644 index 0000000..9783442 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/request/youtube/YTRequest.java @@ -0,0 +1,39 @@ +package com.fpghoti.biscuit.audio.request.youtube; + +import com.fpghoti.biscuit.audio.request.PlayRequest; +import com.fpghoti.biscuit.audio.request.RequestType; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.TextChannel; + +public class YTRequest extends PlayRequest{ + + private boolean searchMode; + + public YTRequest(Message message, String identifier) { + this(message.getTextChannel(), message.getAuthor().getId(), identifier); + } + + public YTRequest(TextChannel channel, String authorId, String identifier) { + super(channel, authorId, identifier); + searchMode = false; + } + + public boolean inSearchMode() { + return searchMode; + } + + public void enableSearchMode() { + searchMode = true; + } + + public void disableSearchMode() { + searchMode = false; + } + + @Override + public RequestType getType() { + return RequestType.YOUTUBE; + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/result/YTResultHandler.java b/src/main/java/com/fpghoti/biscuit/audio/result/YTResultHandler.java new file mode 100644 index 0000000..a45371e --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/result/YTResultHandler.java @@ -0,0 +1,85 @@ +package com.fpghoti.biscuit.audio.result; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.audio.AudioScheduler; +import com.fpghoti.biscuit.audio.request.PlayRequest; +import com.fpghoti.biscuit.audio.request.youtube.YTPriorityRequest; +import com.fpghoti.biscuit.audio.request.youtube.YTRequest; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.rest.MessageText; +import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; +import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; +import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; + +public class YTResultHandler implements AudioLoadResultHandler { + + private Biscuit biscuit; + private YTRequest request; + + public YTResultHandler(YTRequest request) { + this.request = request; + this.biscuit = request.getBiscuit(); + } + + public PlayRequest getRequest() { + return request; + } + + public void handleTrack(AudioTrack track) { + AudioScheduler sched = biscuit.getAudioScheduler(); + + switch(request.getType()) { + + case YOUTUBE: + sched.queue(track, request.getAuthorId(), request.getRequestChannel()); + break; + + case YOUTUBE_PRIORITY: + YTPriorityRequest prq = (YTPriorityRequest) request; + sched.queue(track, request.getAuthorId(), request.getRequestChannel(), prq.getSlot()); + break; + + case YOUTUBE_IMMEDIATE: + sched.queue(track, request.getAuthorId(), request.getRequestChannel(), 1); + if(!sched.getQueue().isEmpty()) { + sched.startPlaying(); + } + break; + + default: + biscuit.error("YouTube result handler received an incompatible request."); + break; + + } + } + + @Override + public void trackLoaded(AudioTrack track) { + handleTrack(track); + } + + @Override + public void playlistLoaded(AudioPlaylist playlist) { + AudioTrack track = playlist.getTracks().get(0); + handleTrack(track); + } + + @Override + public void noMatches() { + if(!request.inSearchMode()) { + biscuit.log("Exact match not found. Searching instead..."); + request.enableSearchMode(); + Main.getPlayerManager().loadItemOrdered(biscuit.getGuild(),"ytsearch:" + request.getIdentifier(), new YTResultHandler(request)); + }else { + MessageText.send(request.getRequestChannel(), "Song match not found."); + } + } + + @Override + public void loadFailed(FriendlyException exception) { + exception.printStackTrace(); + MessageText.send(request.getRequestChannel(), "An error was encountered while attempting to load audio."); + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/PlayCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/PlayCommand.java deleted file mode 100644 index ae1a162..0000000 --- a/src/main/java/com/fpghoti/biscuit/commands/client/PlayCommand.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fpghoti.biscuit.commands.client; - -import com.fpghoti.biscuit.Main; -import com.fpghoti.biscuit.audio.AudioHandler; -import com.fpghoti.biscuit.audio.AudioResultHandler; -import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.base.MusicClientCommand; -import com.fpghoti.biscuit.rest.MessageText; -import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; - -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.TextChannel; -import net.dv8tion.jda.api.entities.VoiceChannel; -import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; -import net.dv8tion.jda.api.managers.AudioManager; - -public class PlayCommand extends MusicClientCommand{ - - public PlayCommand() { - name = "Play"; - description = "Plays the specified song or plays a song found using search parameters."; - usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "play "; - minArgs = 1; - maxArgs = 2000; - identifiers.add("play"); - } - - @Override - public void execute(String[] args, GuildMessageReceivedEvent event) { - Guild guild = event.getGuild(); - Biscuit b = Biscuit.getBiscuit(guild); - TextChannel tchannel = event.getChannel(); - - String searchPhrase = args[0]; - if(args.length > 1) { - for(int i = 1; i < args.length; i++) { - searchPhrase = searchPhrase + " " + args[i]; - } - } - - b.log(event.getAuthor().getName() + " issued a command: -play " + searchPhrase); - - String vcname = ""; - if(!event.getMember().getVoiceState().inVoiceChannel()) { - MessageText.send(tchannel, "You must be in a voice channel to do this!"); - return; - } - vcname = event.getMember().getVoiceState().getChannel().getName(); - String[] musicChannels = b.getProperties().getMusicChannels(); - if(musicChannels.length >= 1) { - boolean found = false; - for(String cname : musicChannels) { - if(event.getMember().getVoiceState().getChannel().getName().equalsIgnoreCase(cname)) { - found = true; - break; - } - } - if(found == false) { - MessageText.send(tchannel, "You are not in a channel that is authorized to use the music player."); - return; - } - } - - if(b.getAudioPlayer().getPlayingTrack() != null && guild.getAudioManager().isConnected() && !guild.getAudioManager().getConnectedChannel().getMembers().contains(event.getMember())) { - MessageText.send(tchannel, "Music is already playing in a voice channel. Connect to " - + "that channel, then queue your song."); - return; - } - - VoiceChannel channel = guild.getVoiceChannelsByName(vcname, true).get(0); - AudioManager manager = guild.getAudioManager(); - - manager.setSendingHandler(new AudioHandler(b.getAudioPlayer())); - manager.openAudioConnection(channel); - - AudioPlayerManager playerManager = Main.getPlayerManager(); - String vidid = getID(event.getMessage().getContentRaw().split(" ")[1]); - - playerManager.loadItemOrdered(guild, vidid, new AudioResultHandler(event.getAuthor().getId(), tchannel, false, searchPhrase, false, false)); - } - - private String getID(String url) { - String[] s = url.split("="); - if(s.length > 1) { - return s[1].split("&")[0]; - } - return url; - } - -} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/PlayFirstCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/PlayFirstCommand.java deleted file mode 100644 index b361056..0000000 --- a/src/main/java/com/fpghoti/biscuit/commands/client/PlayFirstCommand.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.fpghoti.biscuit.commands.client; - -import com.fpghoti.biscuit.Main; -import com.fpghoti.biscuit.audio.AudioHandler; -import com.fpghoti.biscuit.audio.AudioResultHandler; -import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.base.MusicClientCommand; -import com.fpghoti.biscuit.rest.MessageText; -import com.fpghoti.biscuit.util.PermUtil; -import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; - -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.TextChannel; -import net.dv8tion.jda.api.entities.VoiceChannel; -import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; -import net.dv8tion.jda.api.managers.AudioManager; - -public class PlayFirstCommand extends MusicClientCommand{ - - public PlayFirstCommand() { - name = "Play First"; - description = "Places specified song at the front of the queue."; - usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "playfirst "; - minArgs = 1; - maxArgs = 2000; - identifiers.add("playfirst"); - } - - @Override - public void execute(String[] args, GuildMessageReceivedEvent event) { - Guild guild = event.getGuild(); - Biscuit b = Biscuit.getBiscuit(guild); - TextChannel tchannel = event.getChannel(); - - String searchPhrase = args[0]; - if(args.length > 1) { - for(int i = 1; i < args.length; i++) { - searchPhrase = searchPhrase + " " + args[i]; - } - } - - b.log(event.getAuthor().getName() + " issued a command: -play " + searchPhrase); - - String vcname = ""; - - if(!PermUtil.isMod(event.getMember())) { - MessageText.send(tchannel, "You do not have permission to do this!"); - return; - } - - if(!event.getMember().getVoiceState().inVoiceChannel()) { - MessageText.send(tchannel, "You must be in a voice channel to do this!"); - return; - } - vcname = event.getMember().getVoiceState().getChannel().getName(); - String[] musicChannels = b.getProperties().getMusicChannels(); - if(musicChannels.length >= 1) { - boolean found = false; - for(String cname : musicChannels) { - if(event.getMember().getVoiceState().getChannel().getName().equalsIgnoreCase(cname)) { - found = true; - break; - } - } - if(found == false) { - MessageText.send(tchannel, "You are not in a channel that is authorized to use the music player."); - return; - } - } - - if(b.getAudioPlayer().getPlayingTrack() != null && guild.getAudioManager().isConnected() && !guild.getAudioManager().getConnectedChannel().getMembers().contains(event.getMember())) { - MessageText.send(tchannel, "Music is already playing in a voice channel. Connect to " - + "that channel, then queue your song."); - return; - } - - VoiceChannel channel = guild.getVoiceChannelsByName(vcname, true).get(0); - AudioManager manager = guild.getAudioManager(); - - manager.setSendingHandler(new AudioHandler(b.getAudioPlayer())); - manager.openAudioConnection(channel); - - AudioPlayerManager playerManager = Main.getPlayerManager(); - String vidid = getID(event.getMessage().getContentRaw().split(" ")[1]); - - playerManager.loadItemOrdered(guild, vidid, new AudioResultHandler(event.getAuthor().getId(), tchannel, false, searchPhrase, true, false)); - } - - private String getID(String url) { - String[] s = url.split("="); - if(s.length > 1) { - return s[1].split("&")[0]; - } - return url; - } - -} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/SkipCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/SkipCommand.java deleted file mode 100644 index ec7c52f..0000000 --- a/src/main/java/com/fpghoti/biscuit/commands/client/SkipCommand.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.fpghoti.biscuit.commands.client; - -import com.fpghoti.biscuit.Main; -import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.base.MusicClientCommand; -import com.fpghoti.biscuit.rest.MessageText; - -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; - -public class SkipCommand extends MusicClientCommand{ - - public SkipCommand() { - name = "Skip"; - description = "Sends a vote to skip the song that is currently playing."; - usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "skip"; - minArgs = 0; - maxArgs = 0; - identifiers.add("skip"); - } - - @Override - public void execute(String[] args, GuildMessageReceivedEvent event) { - - //TODO Redo vote skipping. It does not function correctly. - - Biscuit b = Biscuit.getBiscuit(event.getGuild()); - b.log(event.getAuthor().getName() + " issued a command: -skip"); - - if(b.getAudioPlayer().getPlayingTrack() == null) { - MessageText.send(event.getChannel(), "There is not a song playing for you to skip!"); - return; - } - - if(!event.getGuild().getAudioManager().getConnectedChannel().getMembers().contains(event.getMember())) { - MessageText.send(event.getChannel(), "You need to be in the same voice channel in order to skip!"); - return; - } - - if(b.getAudioScheduler().getVotes() >= (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() - 1) / 2) { - MessageText.send(event.getChannel(), "Skip vote status: **[" + ( b.getAudioScheduler().getVotes() + 1) + "/" - + (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() - 1) + "]**" - + "\nSkipping current track."); - if(b.getAudioScheduler().getQueue().getNext() != null ) { - MessageEmbed next = b.getAudioScheduler().getQueue().getNext().getEmbedMessage("Now Playing:"); - MessageText.send(event.getChannel(), next); - } - b.getAudioScheduler().skip(); - return; - } - if(b.getAudioScheduler().voteSkip(event.getAuthor().getId())) { - MessageText.send(event.getChannel(), "You voted to skip the current track."); - }else { - MessageText.send(event.getChannel(), "You cannot vote to skip this track again." - + "\nSkip vote status: **[" + b.getAudioScheduler().getVotes() + "/" - + (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() - 1) + "]**"); - } - - if(b.getAudioScheduler().getVotes() >= (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() - 1) / 2) { - MessageText.send(event.getChannel(), "Skip vote status: **[" + b.getAudioScheduler().getVotes() + "/" - + event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() + "]**" - + "\nSkipping current track."); - if(b.getAudioScheduler().getQueue().getNext() != null ) { - MessageEmbed next = b.getAudioScheduler().getQueue().getNext().getEmbedMessage("Now Playing:"); - MessageText.send(event.getChannel(), next); - } - b.getAudioScheduler().skip(); - } - - } - -} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/ClearCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/ClearCommand.java new file mode 100644 index 0000000..5fae2dc --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/ClearCommand.java @@ -0,0 +1,32 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; +import com.fpghoti.biscuit.util.PermUtil; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class ClearCommand extends MusicClientCommand{ + + public ClearCommand() { + name = "Clear"; + description = "Clears all upcoming songs from the queue."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "clear"; + minArgs = 0; + maxArgs = 0; + identifiers.add("clear"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -clear"); + if(PermUtil.hasMusicControl(event.getMember())) { + MessageText.send(event.getChannel(), "Cleared all upcoming songs from the queue."); + b.getAudioScheduler().getQueue().clear(); + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/ClearUserSongsCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/ClearUserSongsCommand.java new file mode 100644 index 0000000..af1f6a6 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/ClearUserSongsCommand.java @@ -0,0 +1,36 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; +import com.fpghoti.biscuit.util.PermUtil; + +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class ClearUserSongsCommand extends MusicClientCommand{ + + public ClearUserSongsCommand() { + name = "Clear User Songs"; + description = "Clears all upcoming songs from specified user."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "clearusersongs <@user>"; + minArgs = 1; + maxArgs = 1; + identifiers.add("clearusersongs"); + identifiers.add("cus"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -clearusersongs " + args[0]); + if(PermUtil.hasMusicControl(event.getMember())) { + for(Member m : event.getMessage().getMentionedMembers()) { + MessageText.send(event.getChannel(), "Clearing all upcoming tracks added by **" + m.getEffectiveName() + "**."); + b.getAudioScheduler().getQueue().removeUserTracks(m.getId()); + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/ForceSkipCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/ForceSkipCommand.java similarity index 68% rename from src/main/java/com/fpghoti/biscuit/commands/client/ForceSkipCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/client/music/ForceSkipCommand.java index be7b047..ec9d172 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/ForceSkipCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/ForceSkipCommand.java @@ -1,4 +1,4 @@ -package com.fpghoti.biscuit.commands.client; +package com.fpghoti.biscuit.commands.client.music; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; @@ -6,7 +6,6 @@ import com.fpghoti.biscuit.commands.base.MusicClientCommand; import com.fpghoti.biscuit.rest.MessageText; import com.fpghoti.biscuit.util.PermUtil; -import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; public class ForceSkipCommand extends MusicClientCommand{ @@ -24,13 +23,9 @@ public class ForceSkipCommand extends MusicClientCommand{ public void execute(String[] args, GuildMessageReceivedEvent event) { Biscuit b = Biscuit.getBiscuit(event.getGuild()); b.log(event.getAuthor().getName() + " issued a command: -forceskip"); - if(PermUtil.isMod(event.getMember())) { + if(PermUtil.hasMusicControl(event.getMember())) { MessageText.send(event.getChannel(), "Force skipping current song."); - if(b.getAudioScheduler().getQueue().getNext() != null ) { - MessageEmbed next = b.getAudioScheduler().getQueue().getNext().getEmbedMessage("Now Playing:"); - MessageText.send(event.getChannel(), next); - } - b.getAudioScheduler().skip(); + b.getAudioScheduler().skip(event.getChannel()); } } diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/ForceSkipToCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/ForceSkipToCommand.java new file mode 100644 index 0000000..e88039b --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/ForceSkipToCommand.java @@ -0,0 +1,38 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; +import com.fpghoti.biscuit.util.PermUtil; +import com.fpghoti.biscuit.util.Util; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class ForceSkipToCommand extends MusicClientCommand{ + + public ForceSkipToCommand() { + name = "Force Skip To"; + description = "Force skips all songs until the specified track."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "forceskipto "; + minArgs = 1; + maxArgs = 1; + identifiers.add("forceskipto"); + identifiers.add("fst"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -forceskipto " + args[0]); + if(PermUtil.hasMusicControl(event.getMember())) { + if(Util.isDigit(args[0])) { + int place = Integer.parseInt(args[0]); + MessageText.send(event.getChannel(), "Force skipping to queue position **" + place + "**."); + b.getAudioScheduler().getQueue().removeTracksBefore(place); + b.getAudioScheduler().skip(event.getChannel()); + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/LoopMusicCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/LoopMusicCommand.java similarity index 88% rename from src/main/java/com/fpghoti/biscuit/commands/client/LoopMusicCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/client/music/LoopMusicCommand.java index e929433..73577a1 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/LoopMusicCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/LoopMusicCommand.java @@ -1,4 +1,4 @@ -package com.fpghoti.biscuit.commands.client; +package com.fpghoti.biscuit.commands.client.music; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; @@ -23,7 +23,7 @@ public class LoopMusicCommand extends MusicClientCommand{ public void execute(String[] args, GuildMessageReceivedEvent event) { Biscuit b = Biscuit.getBiscuit(event.getGuild()); b.log(event.getAuthor().getName() + " issued a command: -loopmusic"); - if(PermUtil.isMod(event.getMember())) { + if(PermUtil.hasMusicControl(event.getMember())) { if(!b.getAudioScheduler().isLooping()) { MessageText.send(event.getChannel(), "Setting all music to loop."); b.getAudioScheduler().setLooping(true); diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/MoveToCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/MoveToCommand.java new file mode 100644 index 0000000..f6e227a --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/MoveToCommand.java @@ -0,0 +1,37 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; +import com.fpghoti.biscuit.util.PermUtil; +import com.fpghoti.biscuit.util.Util; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class MoveToCommand extends MusicClientCommand{ + + public MoveToCommand() { + name = "Move To"; + description = "Moves track to specified position."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "moveto "; + minArgs = 2; + maxArgs = 2; + identifiers.add("moveto"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -moveto " + args[0] + " " + args[1]); + if(PermUtil.hasMusicControl(event.getMember())) { + if(Util.isDigit(args[0]) && Util.isDigit(args[1])) { + int oldPlace = Integer.parseInt(args[0]); + int newPlace = Integer.parseInt(args[1]); + MessageText.send(event.getChannel(), "The specified track was moved." ); + b.getAudioScheduler().getQueue().moveToPlace(oldPlace, newPlace); + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/NowPlayingCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/NowPlayingCommand.java similarity index 93% rename from src/main/java/com/fpghoti/biscuit/commands/client/NowPlayingCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/client/music/NowPlayingCommand.java index cf39c1b..d3af141 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/NowPlayingCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/NowPlayingCommand.java @@ -1,4 +1,4 @@ -package com.fpghoti.biscuit.commands.client; +package com.fpghoti.biscuit.commands.client.music; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/PauseCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/PauseCommand.java similarity index 88% rename from src/main/java/com/fpghoti/biscuit/commands/client/PauseCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/client/music/PauseCommand.java index 596b595..c0199cb 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/PauseCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/PauseCommand.java @@ -1,4 +1,4 @@ -package com.fpghoti.biscuit.commands.client; +package com.fpghoti.biscuit.commands.client.music; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; @@ -23,7 +23,7 @@ public class PauseCommand extends MusicClientCommand{ public void execute(String[] args, GuildMessageReceivedEvent event) { Biscuit b = Biscuit.getBiscuit(event.getGuild()); b.log(event.getAuthor().getName() + " issued a command: -pause"); - if(PermUtil.isMod(event.getMember())) { + if(PermUtil.hasMusicControl(event.getMember())) { if(!b.getAudioPlayer().isPaused()) { b.getAudioPlayer().setPaused(true); MessageText.send(event.getChannel(), "Paused the current track."); diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/PlayCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/PlayCommand.java new file mode 100644 index 0000000..764a236 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/PlayCommand.java @@ -0,0 +1,42 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.audio.PlayCommandUtil; +import com.fpghoti.biscuit.audio.request.youtube.YTRequest; +import com.fpghoti.biscuit.audio.result.YTResultHandler; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; + +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class PlayCommand extends MusicClientCommand{ + + public PlayCommand() { + name = "Play"; + description = "Plays the specified song or plays a song found using search parameters."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "play "; + minArgs = 1; + maxArgs = 2000; + identifiers.add("play"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Guild guild = event.getGuild(); + Biscuit b = Biscuit.getBiscuit(guild); + + String searchPhrase = PlayCommandUtil.getSearchPhrase(args); + + b.log(event.getAuthor().getName() + " issued a command: -play " + searchPhrase); + + boolean connected = PlayCommandUtil.connectToChannel(event); + if(!connected) { + return; + } + + YTRequest request = new YTRequest(event.getMessage(), searchPhrase); + Main.getPlayerManager().loadItemOrdered(guild, PlayCommandUtil.getID(event), new YTResultHandler(request)); + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/PlayFirstCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/PlayFirstCommand.java new file mode 100644 index 0000000..b8931ae --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/PlayFirstCommand.java @@ -0,0 +1,52 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.audio.PlayCommandUtil; +import com.fpghoti.biscuit.audio.request.youtube.YTPriorityRequest; +import com.fpghoti.biscuit.audio.request.youtube.YTRequest; +import com.fpghoti.biscuit.audio.result.YTResultHandler; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; +import com.fpghoti.biscuit.util.PermUtil; + +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class PlayFirstCommand extends MusicClientCommand{ + + public PlayFirstCommand() { + name = "Play First"; + description = "Places specified song at the front of the queue."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "playfirst "; + minArgs = 1; + maxArgs = 2000; + identifiers.add("playfirst"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Guild guild = event.getGuild(); + Biscuit b = Biscuit.getBiscuit(guild); + TextChannel tchannel = event.getChannel(); + + String searchPhrase = PlayCommandUtil.getSearchPhrase(args); + + b.log(event.getAuthor().getName() + " issued a command: -playfirst " + searchPhrase); + + if(!PermUtil.hasMusicControl(event.getMember())) { + MessageText.send(tchannel, "You do not have permission to do this!"); + return; + } + + boolean connected = PlayCommandUtil.connectToChannel(event); + if(!connected) { + return; + } + + YTRequest request = new YTPriorityRequest(event.getMessage(), searchPhrase, 1); + Main.getPlayerManager().loadItemOrdered(guild, PlayCommandUtil.getID(event), new YTResultHandler(request)); + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/QueueCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/QueueCommand.java similarity index 95% rename from src/main/java/com/fpghoti/biscuit/commands/client/QueueCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/client/music/QueueCommand.java index d5a34e9..622e575 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/QueueCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/QueueCommand.java @@ -1,4 +1,4 @@ -package com.fpghoti.biscuit.commands.client; +package com.fpghoti.biscuit.commands.client.music; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.audio.queue.AudioQueue; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/RemoveCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/RemoveCommand.java new file mode 100644 index 0000000..67c2cff --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/RemoveCommand.java @@ -0,0 +1,36 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; +import com.fpghoti.biscuit.util.PermUtil; +import com.fpghoti.biscuit.util.Util; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class RemoveCommand extends MusicClientCommand{ + + public RemoveCommand() { + name = "Remove"; + description = "Removes song from specified position in queue."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "remove "; + minArgs = 1; + maxArgs = 1; + identifiers.add("remove"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -remove " + args[0]); + if(PermUtil.hasMusicControl(event.getMember())) { + if(Util.isDigit(args[0])) { + int place = Integer.parseInt(args[0]); + MessageText.send(event.getChannel(), "Removing track at position **" + place + "**."); + b.getAudioScheduler().getQueue().removeTrack(place); + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/ShuffleCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/ShuffleCommand.java new file mode 100644 index 0000000..11aa1e2 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/ShuffleCommand.java @@ -0,0 +1,33 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class ShuffleCommand extends MusicClientCommand{ + + public ShuffleCommand() { + name = "Shuffle"; + description = "Shuffles the sender's songs in the queue."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "shuffle"; + minArgs = 0; + maxArgs = 0; + identifiers.add("shuffle"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -shuffle"); + if(b.getAudioScheduler().getQueue().getLastTrack() != null ) { + b.getAudioScheduler().getQueue().shuffleUserTracks(event.getAuthor().getId()); + MessageText.send(event.getChannel(), "All songs that you have added to the queue have been shuffled."); + }else { + MessageText.send(event.getChannel(), "No song is currently playing."); + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/SkipAllCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/SkipAllCommand.java new file mode 100644 index 0000000..52602fe --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/SkipAllCommand.java @@ -0,0 +1,33 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; +import com.fpghoti.biscuit.util.PermUtil; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class SkipAllCommand extends MusicClientCommand{ + + public SkipAllCommand() { + name = "Skip All"; + description = "Forces the all songs to be skipped."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "skipall"; + minArgs = 0; + maxArgs = 0; + identifiers.add("skipall"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -skipall"); + if(PermUtil.hasMusicControl(event.getMember())) { + MessageText.send(event.getChannel(), "Force skipping all songs."); + b.getAudioScheduler().getQueue().clear(); + b.getAudioScheduler().skip(event.getChannel()); + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/SkipCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/SkipCommand.java new file mode 100644 index 0000000..96a0524 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/SkipCommand.java @@ -0,0 +1,126 @@ +package com.fpghoti.biscuit.commands.client.music; + +import java.util.ArrayList; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.audio.AudioScheduler; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; + +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.entities.VoiceChannel; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class SkipCommand extends MusicClientCommand{ + + public SkipCommand() { + name = "Skip"; + description = "Sends a vote to skip the song that is currently playing."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "skip"; + minArgs = 0; + maxArgs = 0; + identifiers.add("skip"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + + Guild guild = event.getGuild(); + Biscuit biscuit = Biscuit.getBiscuit(guild); + biscuit.log(event.getAuthor().getName() + " issued a command: -skip"); + + TextChannel cmdChannel = event.getChannel(); + + //Bot is not connected to voice channel. Do nothing. + if(!guild.getAudioManager().isConnected()) { + MessageText.send(event.getChannel(), "The music player is not connected to a voice channel!"); + return; + } + + VoiceChannel voice = guild.getAudioManager().getConnectedChannel(); + + //Bot is connected to a voice channel in the guild, and the command sender is not in the channel. + //Do nothing + if(!voice.getMembers().contains(event.getMember())) { + MessageText.send(cmdChannel, "You need to be in the same voice channel in order to skip!"); + return; + } + + //No song is playing. Do nothing. + if(biscuit.getAudioPlayer().getPlayingTrack() == null) { + MessageText.send(cmdChannel, "There is not a song playing for you to skip!"); + return; + } + + AudioScheduler sched = biscuit.getAudioScheduler(); + boolean skip = false; + + //Get number of users connected to the channel + int count = nonBotCount(voice); + + //Determine amount of votes needed to skip + int votesNeeded = count / 2; + if(votesNeeded * 2 < count) { + votesNeeded++; + } + + int votes = 1; + + //If sender alone + if(count == 1) { + skip = true; //approve skip + }else{ + String id = event.getAuthor().getId(); + + //Check if command sender has already voted + if(sched.hasSkipped(id)) { + MessageText.send(cmdChannel, "You have already voted to skip!"); + return; + } + + //Save vote + sched.voteSkip(id); + + //Get updated vote count + votes = sched.getVotes(); + + //Check if enough to skip + if(votes >= votesNeeded) { + skip = true; //approve skip + } + } + + if(skip) { + //Skip has been approved, so skip + MessageText.send(cmdChannel, "**" + votes + "/" + count + "** voted to skip. Skipping current track."); + sched.skip(cmdChannel); + }else { + //Skip has not been approved, so send vote update message + int remaining = votesNeeded - votes; + + String words = " vote is "; + if(remaining != 1) { //make word singular/plural as needed + words = " votes are "; + } + + MessageText.send(cmdChannel, "**" + votes + "/" + count + "** voted to skip. **" + remaining + "** more" + words + "needed to" + + " skip the current track."); + } + + } + + private int nonBotCount(VoiceChannel c) { + int count = 0; + ArrayList members = new ArrayList(c.getMembers()); + for(Member m : members) { + if(!m.getUser().isBot()) { + count++; + } + } + return count; + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/TogglePauseCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/TogglePauseCommand.java similarity index 89% rename from src/main/java/com/fpghoti/biscuit/commands/client/TogglePauseCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/client/music/TogglePauseCommand.java index a366a8d..bfbdd1c 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/TogglePauseCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/TogglePauseCommand.java @@ -1,4 +1,4 @@ -package com.fpghoti.biscuit.commands.client; +package com.fpghoti.biscuit.commands.client.music; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; @@ -24,7 +24,7 @@ public class TogglePauseCommand extends MusicClientCommand{ public void execute(String[] args, GuildMessageReceivedEvent event) { Biscuit b = Biscuit.getBiscuit(event.getGuild()); b.log(event.getAuthor().getName() + " issued a command: -togglepause"); - if(PermUtil.isMod(event.getMember())) { + if(PermUtil.hasMusicControl(event.getMember())) { if(b.getAudioPlayer().isPaused()) { b.getAudioPlayer().setPaused(false); MessageText.send(event.getChannel(), "Unpaused the current track."); diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/UnpauseCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/UnpauseCommand.java similarity index 77% rename from src/main/java/com/fpghoti/biscuit/commands/client/UnpauseCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/client/music/UnpauseCommand.java index d066a16..9c0b350 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/UnpauseCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/UnpauseCommand.java @@ -1,14 +1,14 @@ -package com.fpghoti.biscuit.commands.client; +package com.fpghoti.biscuit.commands.client.music; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.base.ClientCommand; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; import com.fpghoti.biscuit.rest.MessageText; import com.fpghoti.biscuit.util.PermUtil; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; -public class UnpauseCommand extends ClientCommand{ +public class UnpauseCommand extends MusicClientCommand{ public UnpauseCommand() { name = "Unpause"; @@ -17,13 +17,14 @@ public class UnpauseCommand extends ClientCommand{ minArgs = 0; maxArgs = 0; identifiers.add("unpause"); + identifiers.add("resume"); } @Override public void execute(String[] args, GuildMessageReceivedEvent event) { Biscuit b = Biscuit.getBiscuit(event.getGuild()); b.log(event.getAuthor().getName() + " issued a command: -unpause"); - if(PermUtil.isMod(event.getMember())) { + if(PermUtil.hasMusicControl(event.getMember())) { if(b.getAudioPlayer().isPaused()) { b.getAudioPlayer().setPaused(false); MessageText.send(event.getChannel(), "Unpaused the current track."); diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/music/VolumeCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/VolumeCommand.java new file mode 100644 index 0000000..113fb3a --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/VolumeCommand.java @@ -0,0 +1,50 @@ +package com.fpghoti.biscuit.commands.client.music; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.rest.MessageText; +import com.fpghoti.biscuit.util.PermUtil; +import com.fpghoti.biscuit.util.Util; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; + +public class VolumeCommand extends MusicClientCommand{ + + public VolumeCommand() { + name = "Volume"; + description = "Changes the player volume or displays the current volume."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "volume [0-150]"; + minArgs = 0; + maxArgs = 1; + identifiers.add("volume"); + identifiers.add("vol"); + } + + @Override + public void execute(String[] args, GuildMessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + + if(args.length < 1) { + b.log(event.getAuthor().getName() + " issued a command: -volume"); + MessageText.send(event.getChannel(), "The current volume is: **" + b.getAudioPlayer().getVolume() + "**."); + return; + } + + b.log(event.getAuthor().getName() + " issued a command: -volume " + args[0]); + + if(PermUtil.hasMusicControl(event.getMember())) { + if(Util.isDigit(args[0])) { + int vol = Integer.parseInt(args[0]); + if(vol < 0) { + vol = 0; + }else if(vol > 150) { + vol = 150; + } + b.getAudioPlayer().setVolume(vol); + MessageText.send(event.getChannel(), "The volume was set to **" + b.getAudioPlayer().getVolume() + "**."); + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/WipeQueueCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/music/WipeQueueCommand.java similarity index 88% rename from src/main/java/com/fpghoti/biscuit/commands/client/WipeQueueCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/client/music/WipeQueueCommand.java index 50c19b7..43675f7 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/WipeQueueCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/music/WipeQueueCommand.java @@ -1,4 +1,4 @@ -package com.fpghoti.biscuit.commands.client; +package com.fpghoti.biscuit.commands.client.music; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; @@ -24,7 +24,7 @@ public class WipeQueueCommand extends MusicClientCommand{ public void execute(String[] args, GuildMessageReceivedEvent event) { Biscuit b = Biscuit.getBiscuit(event.getGuild()); b.log(event.getAuthor().getName() + " issued a command: -wipequeue"); - if(PermUtil.isMod(event.getMember())) { + if(PermUtil.hasMusicControl(event.getMember())) { b.getAudioScheduler().wipeQueue(); MessageText.send(event.getChannel(), "Removed upcoming songs from the music queue."); } diff --git a/src/main/java/com/fpghoti/biscuit/config/BiscuitConfig.java b/src/main/java/com/fpghoti/biscuit/config/BiscuitConfig.java index acd6b50..04fce65 100644 --- a/src/main/java/com/fpghoti/biscuit/config/BiscuitConfig.java +++ b/src/main/java/com/fpghoti/biscuit/config/BiscuitConfig.java @@ -180,6 +180,7 @@ public class BiscuitConfig { added = addProperty("Kick-DM-Invite", "", prop, added, silent); added = addProperty("Allow-Music-Bot", "true", prop, added, silent); added = addProperty("Music-Channels", "", prop, added, silent); + added = addProperty("Music-Controller-Role", "music-key", prop, added, silent); if(!isMain) { if(code != null) { diff --git a/src/main/java/com/fpghoti/biscuit/config/BiscuitProperties.java b/src/main/java/com/fpghoti/biscuit/config/BiscuitProperties.java index 74fcadd..50ddd79 100644 --- a/src/main/java/com/fpghoti/biscuit/config/BiscuitProperties.java +++ b/src/main/java/com/fpghoti/biscuit/config/BiscuitProperties.java @@ -63,10 +63,10 @@ public class BiscuitProperties { return biscuit.getConfig().getFromConfig(key, biscuit); } - public String getDontNotify(){ - String key = "Dont-Notify-Role"; + public String getMusicControllerRole(){ + String key = "Music-Controller-Role"; if(biscuit.getConfig().getFromConfig(key, biscuit).equalsIgnoreCase("[global]") && biscuit.getGuild() != null) { - return Main.getMainBiscuit().getProperties().getDontNotify(); + return Main.getMainBiscuit().getProperties().getMusicControllerRole(); } return biscuit.getConfig().getFromConfig(key, biscuit); } diff --git a/src/main/java/com/fpghoti/biscuit/util/PermUtil.java b/src/main/java/com/fpghoti/biscuit/util/PermUtil.java index 85f10c8..2ad2596 100644 --- a/src/main/java/com/fpghoti/biscuit/util/PermUtil.java +++ b/src/main/java/com/fpghoti/biscuit/util/PermUtil.java @@ -38,6 +38,21 @@ public class PermUtil { return false; } + public static boolean hasMusicControl(Member member){ + Biscuit biscuit = Biscuit.getBiscuit(member.getGuild()); + if(isAdmin(member) || isMod(member)){ + return true; + }else{ + for(Role role : member.getRoles()){ + if(role.getName().equalsIgnoreCase(biscuit.getProperties().getMusicControllerRole())){ + return true; + } + } + } + + return false; + } + public static boolean hasRole(Member member, String role){ for(Role r : member.getRoles()){ if(r.getName().equalsIgnoreCase(role)){ diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties index 307ab86..b37049b 100644 --- a/src/main/resources/config.properties +++ b/src/main/resources/config.properties @@ -120,6 +120,10 @@ Log-Music-Player = true #Music-Channels = Room 1, Room 2 Music-Channels = +#Users with this role have complete control over the music player. +#Automatically granted to Mods and Admins. +Music-Controller-Role = music-key + #List your custom commands here. This line will always generate blank. #Example - Custom-Command-Names = hello,botcheck,apple Custom-Command-Names =