diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index ce1b8ed..0097452 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.fpghoti Biscuit - 1.6.3 + 1.7 src/main/java @@ -53,6 +53,12 @@ ** + + commons-logging:commons-logging + + ** + + @@ -109,55 +115,6 @@ 1.15-SNAPSHOT provided - - net.java.dev.jna - jna - 4.5.0 - pom - compile - - - org.json - json - 20171018 - pom - compile - - - net.sf.trove4j - trove4j - 3.0.3 - pom - compile - - - org.apache.commons - commons-collections4 - 4.1 - pom - compile - - - org.apache.commons - commons-lang3 - 3.6 - pom - compile - - - com.squareup.okhttp - okhttp - 2.7.5 - pom - compile - - - com.neovisionaries - nv-websocket-client - 2.3 - pom - compile - UTF-8 diff --git a/pom.xml b/pom.xml index 985e37a..e04e8dd 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.fpghoti Biscuit - 1.6.3 + 1.7 src/main/java @@ -57,6 +57,12 @@ ** + + commons-logging:commons-logging + + ** + + @@ -108,7 +114,6 @@ org.tuxdude.logback.extensions logback-colorizer 1.0.1 - com.github.CrabMustard @@ -174,48 +179,6 @@ cage 1.0 - - net.java.dev.jna - jna - 4.5.0 - pom - - - org.json - json - 20171018 - pom - - - net.sf.trove4j - trove4j - 3.0.3 - pom - - - org.apache.commons - commons-collections4 - 4.1 - pom - - - org.apache.commons - commons-lang3 - 3.6 - pom - - - com.squareup.okhttp - okhttp - 2.7.5 - pom - - - com.neovisionaries - nv-websocket-client - 2.3 - pom - javax.activation activation @@ -226,5 +189,10 @@ mail 1.4.7 + + com.sedmelluq + lavaplayer + 1.3.50 + \ No newline at end of file diff --git a/src/main/java/com/fpghoti/biscuit/Main.java b/src/main/java/com/fpghoti/biscuit/Main.java index 86f60f5..0779db8 100644 --- a/src/main/java/com/fpghoti/biscuit/Main.java +++ b/src/main/java/com/fpghoti/biscuit/Main.java @@ -2,39 +2,48 @@ package com.fpghoti.biscuit; import java.io.IOException; import java.util.ArrayList; -import java.util.List; import java.util.Properties; import java.util.Scanner; import org.fusesource.jansi.AnsiConsole; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.BaseCommand; -import com.fpghoti.biscuit.commands.CommandListener; 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.console.GuildSayCommand; import com.fpghoti.biscuit.commands.console.SayCommand; import com.fpghoti.biscuit.commands.console.ShutdownConsoleCommand; +import com.fpghoti.biscuit.listener.CommandListener; import com.fpghoti.biscuit.listener.DMListener; import com.fpghoti.biscuit.listener.GuildListener; import com.fpghoti.biscuit.listener.JoinListener; @@ -46,19 +55,24 @@ import com.fpghoti.biscuit.listener.ReactionListener; import com.fpghoti.biscuit.listener.RoleListener; import com.fpghoti.biscuit.logging.BColor; import com.fpghoti.biscuit.logging.BiscuitLog; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; import ch.qos.logback.core.rolling.RollingFileAppender; import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy; import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.requests.GatewayIntent; +import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder; +import net.dv8tion.jda.api.sharding.ShardManager; import net.dv8tion.jda.api.utils.ChunkingFilter; import net.dv8tion.jda.api.utils.MemberCachePolicy; public class Main { private static JDA jda; + private static ShardManager shardm; public RollingFileAppender we; public SizeAndTimeBasedRollingPolicy wes; @@ -72,6 +86,8 @@ public class Main { public static boolean isPlugin = false; public static boolean shutdownStarted = false; + private static AudioPlayerManager playerManager; + public static void main(String[] args){ final Properties properties = new Properties(); try { @@ -84,8 +100,13 @@ public class Main { AnsiConsole.systemInstall(); log.info(BColor.CYAN_BOLD + "========================= WELCOME TO BISCUIT ========================="); log.info("Running version: " + BColor.MAGENTA_BOLD + version); + + playerManager = new DefaultAudioPlayerManager(); + AudioSourceManagers.registerRemoteSources(playerManager); + mainBiscuit = new Biscuit(null, null, log); startJDA(); + jda.addEventListener(new GuildListener()); jda.addEventListener(new MessageReceiveListener()); jda.addEventListener(new MessageEditListener()); @@ -103,36 +124,45 @@ public class Main { String link = "NULL"; - List commands = CommandManager.getCommands(); - //Client - commands.add(new HelpCommand()); - commands.add(new PingCommand()); - commands.add(new SoftMuteCommand()); - commands.add(new UnSoftMuteCommand()); - commands.add(new NotSpammerCommand()); - commands.add(new RecentSpammersCommand()); - commands.add(new ChanIDCommand()); - commands.add(new UIDCommand()); - commands.add(new ToggleRoleCommand()); - commands.add(new SquareRootCommand()); - commands.add(new AddCommand()); - commands.add(new SubtractCommand()); - commands.add(new MultiplyCommand()); - commands.add(new DivideCommand()); - commands.add(new PowerCommand()); - commands.add(new MakeInviteCommand()); - commands.add(new GetConfigCommand()); - commands.add(new SaveConfigCommand()); - commands.add(new GuildIDCommand()); - commands.add(new WikiCommand()); - + CommandManager.addCommand(new HelpCommand()); + CommandManager.addCommand(new PingCommand()); + CommandManager.addCommand(new SoftMuteCommand()); + CommandManager.addCommand(new UnSoftMuteCommand()); + CommandManager.addCommand(new NotSpammerCommand()); + CommandManager.addCommand(new RecentSpammersCommand()); + CommandManager.addCommand(new ChanIDCommand()); + CommandManager.addCommand(new UIDCommand()); + CommandManager.addCommand(new ToggleRoleCommand()); + CommandManager.addCommand(new SquareRootCommand()); + CommandManager.addCommand(new AddCommand()); + CommandManager.addCommand(new SubtractCommand()); + CommandManager.addCommand(new MultiplyCommand()); + CommandManager.addCommand(new DivideCommand()); + CommandManager.addCommand(new PowerCommand()); + CommandManager.addCommand(new MakeInviteCommand()); + CommandManager.addCommand(new GetConfigCommand()); + CommandManager.addCommand(new SaveConfigCommand()); + CommandManager.addCommand(new GuildIDCommand()); + CommandManager.addCommand(new WikiCommand()); + CommandManager.addCommand(new PlayCommand()); + CommandManager.addCommand(new PlayFirstCommand()); + CommandManager.addCommand(new ForceSkipCommand()); + CommandManager.addCommand(new PauseCommand()); + CommandManager.addCommand(new UnpauseCommand()); + CommandManager.addCommand(new TogglePauseCommand()); + CommandManager.addCommand(new QueueCommand()); + CommandManager.addCommand(new SkipCommand()); + CommandManager.addCommand(new NowPlayingCommand()); + CommandManager.addCommand(new WipeQueueCommand()); + CommandManager.addCommand(new LoopMusicCommand()); + //Console - commands.add(new SayCommand()); - commands.add(new GuildSayCommand()); - commands.add(new ShutdownConsoleCommand()); + CommandManager.addCommand(new SayCommand()); + CommandManager.addCommand(new GuildSayCommand()); + CommandManager.addCommand(new ShutdownConsoleCommand()); link = "https://discord.com/oauth2/authorize?&client_id=" + jda.getSelfUser().getId() + "&permissions=8&scope=bot"; log.info("Connection successful!"); @@ -148,12 +178,13 @@ public class Main { String token = mainBiscuit.getProperties().getToken(); log.info("Connecting bot to Discord."); try{ - jda = JDABuilder.createDefault(token) + shardm = DefaultShardManagerBuilder.createDefault(token) .setChunkingFilter(ChunkingFilter.ALL) .setMemberCachePolicy(MemberCachePolicy.ALL) .enableIntents(GatewayIntent.getIntents(GatewayIntent.DEFAULT)) .enableIntents(GatewayIntent.GUILD_MEMBERS) .build(); + jda = shardm.getShardById(0); try { jda.awaitReady(); } catch (InterruptedException e) { @@ -186,7 +217,11 @@ public class Main { public static ArrayList getBiscuits() { return biscuits; } - + + public static AudioPlayerManager getPlayerManager() { + return playerManager; + } + public static void shutdown() { if(!shutdownStarted) { shutdownStarted = true; @@ -213,11 +248,11 @@ public class Main { public static BiscuitLog getLogger() { return log; } - + public static void registerBiscuit(Biscuit b) { biscuits.add(b); } - + public static void unregisterBiscuit(Biscuit b) { biscuits.remove(b); } diff --git a/src/main/java/com/fpghoti/biscuit/audio/AudioHandler.java b/src/main/java/com/fpghoti/biscuit/audio/AudioHandler.java new file mode 100644 index 0000000..74b41e2 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/AudioHandler.java @@ -0,0 +1,34 @@ +package com.fpghoti.biscuit.audio; + +import java.nio.ByteBuffer; + +import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; +import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame; + +import net.dv8tion.jda.api.audio.AudioSendHandler; + +public class AudioHandler implements AudioSendHandler { + + private final AudioPlayer audioPlayer; + private AudioFrame lastFrame; + + public AudioHandler(AudioPlayer audioPlayer) { + this.audioPlayer = audioPlayer; + } + + @Override + public boolean canProvide() { + lastFrame = audioPlayer.provide(); + return lastFrame != null; + } + + @Override + public ByteBuffer provide20MsAudio() { + return ByteBuffer.wrap(lastFrame.getData()); + } + + @Override + public boolean isOpus() { + return true; + } +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/AudioResultHandler.java b/src/main/java/com/fpghoti/biscuit/audio/AudioResultHandler.java new file mode 100644 index 0000000..55355bd --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/AudioResultHandler.java @@ -0,0 +1,104 @@ +package com.fpghoti.biscuit.audio; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.util.Util; +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 stop; + + public AudioResultHandler(Biscuit biscuit, String uid, TextChannel channel, boolean search, + String searchPhrase, boolean first, boolean stop) { + this.biscuit = biscuit; + this.uid = uid; + this.channel = channel; + this.search = search; + this.searchPhrase = searchPhrase; + this.first = first; + this.stop = stop; + } + + public AudioResultHandler(Biscuit biscuit, String uid, TextChannel channel, boolean search, + String searchPhrase, boolean first) { + this.biscuit = biscuit; + this.uid = uid; + this.channel = channel; + this.search = search; + this.searchPhrase = searchPhrase; + this.first = first; + this.stop = false; + } + + public AudioResultHandler(Biscuit biscuit, String uid, TextChannel channel, boolean search, String searchPhrase) { + this.biscuit = biscuit; + this.uid = uid; + this.channel = channel; + this.search = search; + this.searchPhrase = searchPhrase; + this.first = false; + this.stop = false; + } + + @Override + public void trackLoaded(AudioTrack track) { + if(!stop) { + //TODO fix vevo + //Try to avoid Vevo results if possible. + String title = track.getInfo().title; + if(title.toLowerCase().contains("vevo") || track.getInfo().author.toLowerCase().contains("vevo")) { + title = title.toLowerCase().replace("vevo", "") + " lyrics"; + channel.sendMessage("You tried to load a Vevo video. These are not compatible with the music player." + + " Trying to find alternate song...").queue(); + Main.getPlayerManager().loadItemOrdered(biscuit.getGuild(),"ytsearch:" + title, new AudioResultHandler(biscuit, uid, channel, true, title, first, true)); + return; + } + } + + channel.sendMessage("**Adding to queue: **\n```" + track.getInfo().title + "\nBy: " + + track.getInfo().author + "\nLength: " + Util.getTime(track.getDuration()) +"```").queue(); + if(first) { + biscuit.getAudioScheduler().queueFirst(track, uid, channel); + }else { + biscuit.getAudioScheduler().queue(track, uid, channel); + } + } + + @Override + public void playlistLoaded(AudioPlaylist playlist) { + AudioTrack track = playlist.getTracks().get(0); + channel.sendMessage("**Adding to queue: **\n" + track.getInfo().uri + "\n```" + track.getInfo().title + "\nBy: " + + track.getInfo().author + "\nLength: " + Util.getTime(track.getDuration()) +"```").queue(); + biscuit.getAudioScheduler().queue(track, uid); + } + + + @Override + public void noMatches() { + if(!search) { + biscuit.log("Exact match not found. Searching instead..."); + Main.getPlayerManager().loadItemOrdered(biscuit.getGuild(),"ytsearch:" + searchPhrase, new AudioResultHandler(biscuit, uid, channel, true, searchPhrase)); + }else { + channel.sendMessage("Song match not found.").queue(); + } + } + + @Override + public void loadFailed(FriendlyException exception) { + exception.printStackTrace(); + channel.sendMessage("An error was encountered while attempting to load audio.").queue(); + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/AudioScheduler.java b/src/main/java/com/fpghoti/biscuit/audio/AudioScheduler.java new file mode 100644 index 0000000..63bcbd1 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/AudioScheduler.java @@ -0,0 +1,216 @@ +package com.fpghoti.biscuit.audio; + +import java.util.ArrayList; + +import com.fpghoti.biscuit.audio.queue.AudioQueue; +import com.fpghoti.biscuit.audio.queue.QueuedTrack; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.util.Util; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; +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 net.dv8tion.jda.api.entities.TextChannel; + +public class AudioScheduler extends AudioEventAdapter { + + private Biscuit biscuit; + private AudioQueue queue; + private ArrayList skips; + private boolean loop; + + public AudioScheduler(Biscuit biscuit) { + this.biscuit = biscuit; + this.queue = new AudioQueue(); + this.skips = new ArrayList(); + this.loop = false; + } + + @Override + public void onPlayerPause(AudioPlayer player) { + log("The current track was paused."); + } + + @Override + public void onPlayerResume(AudioPlayer player) { + log("The current track was unpaused."); + } + + @Override + public void onTrackStart(AudioPlayer player, AudioTrack track) { + log("Starting track " + track.getInfo().title + "."); + } + + @Override + public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { + + QueuedTrack qt = queue.getLastTrack(); + String title = track.getInfo().title; + + switch(endReason) { + + case LOAD_FAILED: + warn("Something went wrong while trying to load the current track. The next track will be played instead if available."); + if(qt != null && qt.getCommandChannel() != null) + qt.getCommandChannel().sendMessage("There was an error loading **" + title + "**.").queue(); + break; + case CLEANUP: + log("A track stopped playing due to audio player cleanup."); + if(qt != null && qt.getCommandChannel() != null) + qt.getCommandChannel().sendMessage("Track **" + track.getInfo().title + "** stopped playing due to audio player cleanup.").queue(); + break; + case FINISHED: + log("Finished playing track " + title + "."); + break; + case REPLACED: + log("Skipped track " + title + "."); + break; + case STOPPED: + log("Stopped playing track " + title + "."); + break; + default: + break; + + } + + if (endReason.mayStartNext) { + if(loop) { + queueFirst(track.makeClone(), qt.getUserId(), qt.getCommandChannel()); + } + startPlaying(); + } + } + + @Override + public void onTrackException(AudioPlayer player, AudioTrack track, FriendlyException exception) { + //TODO fix vevo + if(track.getInfo().title.toLowerCase().contains("vevo") || track.getInfo().author.toLowerCase().contains("vevo")) { + QueuedTrack qt = queue.getPreviousTrack(track); + qt.getCommandChannel().sendMessage("**" + track.getInfo().title + "** could not be loaded, because it is a Vevo video.").queue(); + } + biscuit.error("An exception occurred while trying to play a certain track. The next track will be played instead if available."); + startPlaying(); + } + + @Override + public void onTrackStuck(AudioPlayer player, AudioTrack track, long thresholdMs) { + QueuedTrack qt = queue.getPreviousTrack(track); + if(qt != null && qt.getCommandChannel() != null) { + qt.getCommandChannel().sendMessage("The current track has become stuck and will be skipped.").queue(); + } + } + + public void queue(AudioTrack track, String uid) { + queue(track, uid, null); + } + + public void queue(AudioTrack track, String uid, TextChannel channel) { + if(queue.isEmpty() && biscuit.getAudioPlayer().getPlayingTrack() == null) { + queue.addPreviousTrack(new QueuedTrack(biscuit, track, uid, channel)); + biscuit.getAudioPlayer().playTrack(track); + }else { + queue.add(new QueuedTrack(biscuit, track, uid, channel)); + } + } + + public void queueFirst(AudioTrack track, String uid, TextChannel channel) { + if(queue.isEmpty() && biscuit.getAudioPlayer().getPlayingTrack() == null) { + queue.addPreviousTrack(new QueuedTrack(biscuit, track, uid, channel)); + biscuit.getAudioPlayer().playTrack(track); + }else { + queue.addAtPlace(new QueuedTrack(biscuit, track, uid, channel), 1); + } + } + + public void startPlaying() { + if(queue.isEmpty()) { + if(loop) { + return; + } + biscuit.getGuild().getAudioManager().closeAudioConnection(); + skips.clear(); + return; + } + queue.playNext(); + skips.clear(); + } + + public void setLooping(boolean b) { + loop = b; + } + + public boolean isLooping() { + return loop; + } + + public boolean hasSkipped(String id) { + return skips.contains(id); + } + + public boolean voteSkip(String id) { + if(!hasSkipped(id)) { + skips.add(id); + return true; + } + return false; + } + + public int getVotes() { + return skips.size(); + } + + public AudioQueue getQueue(){ + return queue; + } + + public void skip() { + biscuit.getAudioPlayer().stopTrack(); + startPlaying(); + } + + public String getNextMessage() { + if(queue.isEmpty()) { + return null; + } + AudioTrack track = queue.getNext().getTrack(); + return getMessage(track); + } + + public String getMessage(AudioTrack track) { + return getMessage(track, false); + } + + public String getMessage(AudioTrack track, Boolean showRemaining) { + String msg ="**Now Playing: **\n" + track.getInfo().uri + "\n```" + track.getInfo().title + "\nBy: " + + track.getInfo().author + "\nLength: " + Util.getTime(track.getDuration()); + if(showRemaining) { + msg = msg + "\nTime Remaining: " + Util.getTime(track.getDuration() - track.getPosition()) + "```"; + }else { + msg = msg + "```"; + } + return msg; + } + + public void wipeQueue() { + queue.clear(); + } + + public Biscuit getBiscuit() { + return biscuit; + } + + public void log(String message) { + if(biscuit.getProperties().logMusicPlayer()) { + biscuit.log(message); + } + } + + public void warn(String message) { + if(biscuit.getProperties().logMusicPlayer()) { + biscuit.warn(message); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/fpghoti/biscuit/audio/queue/AudioQueue.java b/src/main/java/com/fpghoti/biscuit/audio/queue/AudioQueue.java new file mode 100644 index 0000000..94a3450 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/queue/AudioQueue.java @@ -0,0 +1,132 @@ +package com.fpghoti.biscuit.audio.queue; + +import java.util.ArrayList; + +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; + +public class AudioQueue { + + private ArrayList tracks; + private ArrayList previousTracks; + + public AudioQueue() { + this.tracks = new ArrayList(); + this.previousTracks = new ArrayList(); + } + + public ArrayList getUserTracks(String userId){ + ArrayList tracks = new ArrayList(); + for(QueuedTrack qt : tracks) { + if(qt.getUserId().equals(userId)) { + tracks.add(qt); + } + } + return tracks; + } + + public void removeUserTracks(String userId) { + for(QueuedTrack qt : getUserTracks(userId)) { + tracks.remove(qt); + } + } + + public void playNext() { + QueuedTrack next = tracks.iterator().next(); + tracks.remove(next); + addPreviousTrack(next); + next.getBiscuit().getAudioPlayer().playTrack(next.getTrack()); + } + + public QueuedTrack getTrack(int index){ + return tracks.get(index); + } + + public QueuedTrack getTrack(AudioTrack track) { + for(QueuedTrack qt : tracks) { + if(qt.getTrack() == track) { + return qt; + } + } + return null; + } + + public QueuedTrack getPreviousTrack(AudioTrack track) { + for(QueuedTrack qt : previousTracks) { + if(qt.getTrack() == track) { + return qt; + } + } + return null; + } + + public QueuedTrack getLastTrack() { + if(previousTracks.isEmpty()) { + return null; + } + return previousTracks.get(previousTracks.size() - 1); + } + + public void addPreviousTrack(QueuedTrack track) { + //AudioQueue will remember up to three + //previous tracks for the purposes of + //reporting errors ect. + previousTracks.add(track); + if(previousTracks.size() > 3) { + previousTracks.remove(0); + } + } + + public void add(QueuedTrack track) { + tracks.add(track); + } + + //Goes by viewable place rather than index for + //easy implementation into command. + public boolean addAtPlace(QueuedTrack track, int place) { + if(place < 1 || place > tracks.size()) { + return false; + } + int index = place - 1; + tracks.add(index, track); + return true; + } + + //Goes by viewable place rather than index for + //easy implementation into command. + public boolean moveToPlace(int oldPlace, int newPlace) { + QueuedTrack track = tracks.get(oldPlace - 1); + if(track == null) { + return false; + } + tracks.remove(track); + return addAtPlace(track, newPlace); + } + + //Goes by viewable place rather than index for + //easy implementation into command. + public boolean removeTrack(int place) { + QueuedTrack track = tracks.get(place - 1); + if(track == null) { + return false; + } + tracks.remove(track); + return true; + } + + public QueuedTrack getNext() { + return tracks.get(0); + } + + public boolean isEmpty() { + return tracks.isEmpty(); + } + + public void clear() { + tracks.clear(); + } + + public int size() { + return tracks.size(); + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/audio/queue/QueuedTrack.java b/src/main/java/com/fpghoti/biscuit/audio/queue/QueuedTrack.java new file mode 100644 index 0000000..8b8fdcf --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/audio/queue/QueuedTrack.java @@ -0,0 +1,43 @@ +package com.fpghoti.biscuit.audio.queue; + +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; + +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; + +public class QueuedTrack { + + private Biscuit biscuit; + private AudioTrack track; + private String userId; + private TextChannel channel; + + public QueuedTrack(Biscuit biscuit, AudioTrack track, String userId, TextChannel channel) { + this.biscuit = biscuit; + this.track = track; + this.userId = userId; + this.channel = channel; + } + + public Biscuit getBiscuit() { + return biscuit; + } + + public AudioTrack getTrack() { + return track; + } + + public String getUserId() { + return userId; + } + + public Member getMember() { + return biscuit.getGuild().getMemberById(userId); + } + + public TextChannel getCommandChannel() { + return channel; + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/biscuit/Biscuit.java b/src/main/java/com/fpghoti/biscuit/biscuit/Biscuit.java index 63b0f44..51bdf73 100644 --- a/src/main/java/com/fpghoti/biscuit/biscuit/Biscuit.java +++ b/src/main/java/com/fpghoti/biscuit/biscuit/Biscuit.java @@ -9,6 +9,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.PluginCore; +import com.fpghoti.biscuit.audio.AudioScheduler; import com.fpghoti.biscuit.captcha.BCage; import com.fpghoti.biscuit.config.BiscuitConfig; import com.fpghoti.biscuit.config.BiscuitProperties; @@ -20,6 +21,7 @@ import com.fpghoti.biscuit.timer.task.DecrementTimer; import com.fpghoti.biscuit.timer.task.SoftMuteTimer; import com.fpghoti.biscuit.user.PreUser; import com.github.cage.Cage; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.Permission; @@ -85,6 +87,8 @@ public class Biscuit { private BiscuitConfig config; private BiscuitProperties properties; private BiscuitMessageStore messageStore; + private AudioPlayer player; + private AudioScheduler scheduler; private CopyOnWriteArrayList users = new CopyOnWriteArrayList(); private HashMap rolequeue; @@ -99,6 +103,11 @@ public class Biscuit { config.generateConfig(); this.properties = new BiscuitProperties(this); this.rolequeue = new HashMap(); + this.player = Main.getPlayerManager().createPlayer(); + + scheduler = new AudioScheduler(this); + player.addListener(scheduler); + timer = new Timer(); timers = new ArrayList(); if(!Main.isPlugin) { @@ -143,6 +152,14 @@ public class Biscuit { return guild.getSelfMember().hasPermission(Permission.MANAGE_SERVER); } + public AudioPlayer getAudioPlayer() { + return player; + } + + public AudioScheduler getAudioScheduler() { + return scheduler; + } + public void log(String message) { if(properties == null) { logger.info(message); diff --git a/src/main/java/com/fpghoti/biscuit/commands/CommandManager.java b/src/main/java/com/fpghoti/biscuit/commands/CommandManager.java index cd05e51..164312c 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/CommandManager.java +++ b/src/main/java/com/fpghoti/biscuit/commands/CommandManager.java @@ -5,6 +5,10 @@ import java.util.List; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.ClientCommand; +import com.fpghoti.biscuit.commands.base.ConsoleCommand; +import com.fpghoti.biscuit.commands.base.CustomCommand; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; import com.fpghoti.biscuit.util.PermUtil; import com.fpghoti.biscuit.util.Util; @@ -69,6 +73,11 @@ public class CommandManager { } if(match != null) { + + if(match instanceof MusicClientCommand && !b.getProperties().allowMusicBot()) { + return false; + } + if (trimmedArgs == null || (trimmedArgs.length > 0 && trimmedArgs[0].equals("?"))) { commandReply(e, "``Command:" + " " + match.getName() + "``"); commandReply(e, "``Description:" + " " + match.getDescription() + "``"); @@ -118,6 +127,9 @@ public class CommandManager { } public static void addCommand(BaseCommand command) { + if(command instanceof MusicClientCommand && !Main.getMainBiscuit().getProperties().musicBotEnabled()) { + return; + } commands.add(command); } diff --git a/src/main/java/com/fpghoti/biscuit/commands/ClientCommand.java b/src/main/java/com/fpghoti/biscuit/commands/base/ClientCommand.java similarity index 68% rename from src/main/java/com/fpghoti/biscuit/commands/ClientCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/base/ClientCommand.java index d99dc2f..4967e20 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/ClientCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/base/ClientCommand.java @@ -1,4 +1,7 @@ -package com.fpghoti.biscuit.commands; +package com.fpghoti.biscuit.commands.base; + +import com.fpghoti.biscuit.commands.BaseCommand; +import com.fpghoti.biscuit.commands.CommandType; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/ConsoleCommand.java b/src/main/java/com/fpghoti/biscuit/commands/base/ConsoleCommand.java similarity index 53% rename from src/main/java/com/fpghoti/biscuit/commands/ConsoleCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/base/ConsoleCommand.java index d1456d5..db791ec 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/ConsoleCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/base/ConsoleCommand.java @@ -1,4 +1,7 @@ -package com.fpghoti.biscuit.commands; +package com.fpghoti.biscuit.commands.base; + +import com.fpghoti.biscuit.commands.BaseCommand; +import com.fpghoti.biscuit.commands.CommandType; public abstract class ConsoleCommand extends BaseCommand{ diff --git a/src/main/java/com/fpghoti/biscuit/commands/CustomCommand.java b/src/main/java/com/fpghoti/biscuit/commands/base/CustomCommand.java similarity index 84% rename from src/main/java/com/fpghoti/biscuit/commands/CustomCommand.java rename to src/main/java/com/fpghoti/biscuit/commands/base/CustomCommand.java index 564f745..1e52599 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/CustomCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/base/CustomCommand.java @@ -1,6 +1,8 @@ -package com.fpghoti.biscuit.commands; +package com.fpghoti.biscuit.commands.base; import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.BaseCommand; +import com.fpghoti.biscuit.commands.CommandType; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/base/MusicClientCommand.java b/src/main/java/com/fpghoti/biscuit/commands/base/MusicClientCommand.java new file mode 100644 index 0000000..4499d46 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/base/MusicClientCommand.java @@ -0,0 +1,9 @@ +package com.fpghoti.biscuit.commands.base; + +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public abstract class MusicClientCommand extends ClientCommand{ + + public abstract void execute(String[] args, MessageReceivedEvent event); + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/AddCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/AddCommand.java index ff76925..2fd0afb 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/AddCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/AddCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.Util; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/ChanIDCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/ChanIDCommand.java index 02d8e14..8fab3c0 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/ChanIDCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/ChanIDCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/DivideCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/DivideCommand.java index d6f0a7c..46d2bab 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/DivideCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/DivideCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.Util; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/ForceSkipCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/ForceSkipCommand.java new file mode 100644 index 0000000..69e8c06 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/ForceSkipCommand.java @@ -0,0 +1,34 @@ +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.util.PermUtil; + +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class ForceSkipCommand extends MusicClientCommand{ + + public ForceSkipCommand() { + name = "Force Skip"; + description = "Forces the current song to be skipped."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "forceskip"; + minArgs = 0; + maxArgs = 0; + identifiers.add("forceskip"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -forceskip"); + if(PermUtil.isMod(event.getMember())) { + event.getChannel().sendMessage("Force skipping current song.").queue(); + if(b.getAudioScheduler().getNextMessage() != null ) { + event.getChannel().sendMessage(b.getAudioScheduler().getNextMessage()).queue(); + } + b.getAudioScheduler().skip(); + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/GetConfigCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/GetConfigCommand.java index 18dd4fb..dbbdbf2 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/GetConfigCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/GetConfigCommand.java @@ -5,7 +5,7 @@ import java.util.function.Consumer; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.logging.BColor; import com.fpghoti.biscuit.util.PermUtil; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/GuildIDCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/GuildIDCommand.java index bd53558..559dcea 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/GuildIDCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/GuildIDCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.PermUtil; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/HelpCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/HelpCommand.java index 3290017..d064a26 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/HelpCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/HelpCommand.java @@ -6,9 +6,10 @@ import java.util.List; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; import com.fpghoti.biscuit.commands.BaseCommand; -import com.fpghoti.biscuit.commands.ClientCommand; import com.fpghoti.biscuit.commands.CommandManager; -import com.fpghoti.biscuit.commands.CustomCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; +import com.fpghoti.biscuit.commands.base.CustomCommand; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; import com.fpghoti.biscuit.util.Util; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; @@ -38,7 +39,7 @@ public class HelpCommand extends ClientCommand { } } List commands = new ArrayList(); - + String[] ccs = biscuit.getProperties().getCustomCmds(); for(String s : ccs) { if(!Util.contains(biscuit.getProperties().disabledCommands(), s)) { @@ -53,11 +54,17 @@ public class HelpCommand extends ClientCommand { commands.add(cc); } } - + for(BaseCommand bc : CommandManager.getCommands()) { String bclabel = bc.getUsage().split(" ")[0]; if(!Util.contains(biscuit.getProperties().disabledCommands(), bclabel.replace(Main.getMainBiscuit().getProperties().getCommandSignifier(), ""))) { - commands.add(bc); + if(bc instanceof MusicClientCommand) { + if(biscuit.getProperties().allowMusicBot()) { + commands.add(bc); + } + }else { + commands.add(bc); + } } } int pageCount = (int) Math.ceil((double) commands.size() / 8); diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/LoopMusicCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/LoopMusicCommand.java new file mode 100644 index 0000000..b0cb277 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/LoopMusicCommand.java @@ -0,0 +1,37 @@ +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.util.PermUtil; + +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class LoopMusicCommand extends MusicClientCommand{ + + public LoopMusicCommand() { + name = "Loop Music"; + description = "Enables looping of all songs played."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "loopmusic"; + minArgs = 0; + maxArgs = 0; + identifiers.add("loopmusic"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -loopmusic"); + if(PermUtil.isMod(event.getMember())) { + if(!b.getAudioScheduler().isLooping()) { + event.getChannel().sendMessage("Setting all music to loop.").queue(); + b.getAudioScheduler().setLooping(true); + }else { + event.getChannel().sendMessage("Disabling music looping.").queue(); + b.getAudioScheduler().setLooping(false); + } + + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/MakeInviteCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/MakeInviteCommand.java index 42e02c7..61c07f8 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/MakeInviteCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/MakeInviteCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.PermUtil; import com.fpghoti.biscuit.util.Util; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/MultiplyCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/MultiplyCommand.java index e05baa4..3fd1462 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/MultiplyCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/MultiplyCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.Util; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/NotSpammerCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/NotSpammerCommand.java index a953954..9e123b3 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/NotSpammerCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/NotSpammerCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.PermUtil; import net.dv8tion.jda.api.entities.Member; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/NowPlayingCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/NowPlayingCommand.java new file mode 100644 index 0000000..87540fc --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/NowPlayingCommand.java @@ -0,0 +1,33 @@ +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.sedmelluq.discord.lavaplayer.track.AudioTrack; + +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class NowPlayingCommand extends MusicClientCommand{ + + public NowPlayingCommand() { + name = "Now Playing"; + description = "Displays the currently playing song."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "nowplaying"; + minArgs = 0; + maxArgs = 0; + identifiers.add("nowplaying"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -nowplaying"); + if(b.getAudioPlayer().getPlayingTrack() != null) { + AudioTrack track = b.getAudioPlayer().getPlayingTrack(); + event.getChannel().sendMessage(b.getAudioScheduler().getMessage(track, true)).queue(); + }else { + event.getChannel().sendMessage("No song is currently playing.").queue(); + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/PauseCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/PauseCommand.java new file mode 100644 index 0000000..13d99cc --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/PauseCommand.java @@ -0,0 +1,35 @@ +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.util.PermUtil; + +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class PauseCommand extends MusicClientCommand{ + + public PauseCommand() { + name = "Pause"; + description = "Pauses the current track."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "pause"; + minArgs = 0; + maxArgs = 0; + identifiers.add("pause"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -pause"); + if(PermUtil.isMod(event.getMember())) { + if(!b.getAudioPlayer().isPaused()) { + b.getAudioPlayer().setPaused(true); + event.getChannel().sendMessage("Paused the current track.").queue(); + }else { + event.getChannel().sendMessage("The music player is already paused.").queue(); + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/PingCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/PingCommand.java index e8e1385..e3e6e2c 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/PingCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/PingCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/PlayCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/PlayCommand.java new file mode 100644 index 0000000..1c07662 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/PlayCommand.java @@ -0,0 +1,89 @@ +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.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.MessageReceivedEvent; +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, MessageReceivedEvent event) { + Guild guild = event.getGuild(); + Biscuit b = Biscuit.getBiscuit(guild); + TextChannel tchannel = event.getTextChannel(); + + 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()) { + tchannel.sendMessage("You must be in a voice channel to do this!").queue(); + 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) { + tchannel.sendMessage("You are not in a channel that is authorized to use the music player.").queue(); + return; + } + } + + if(b.getAudioPlayer().getPlayingTrack() != null && guild.getAudioManager().isConnected() && !guild.getAudioManager().getConnectedChannel().getMembers().contains(event.getMember())) { + tchannel.sendMessage("Music is already playing in a voice channel. Connect to " + + "that channel, then queue your song.").queue(); + 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(b,event.getAuthor().getId(), tchannel, false, searchPhrase)); + } + + 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 new file mode 100644 index 0000000..9508ca1 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/PlayFirstCommand.java @@ -0,0 +1,96 @@ +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.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.MessageReceivedEvent; +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, MessageReceivedEvent event) { + Guild guild = event.getGuild(); + Biscuit b = Biscuit.getBiscuit(guild); + TextChannel tchannel = event.getTextChannel(); + + 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())) { + tchannel.sendMessage("You do not have permission to do this!").queue(); + return; + } + + if(!event.getMember().getVoiceState().inVoiceChannel()) { + tchannel.sendMessage("You must be in a voice channel to do this!").queue(); + 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) { + tchannel.sendMessage("You are not in a channel that is authorized to use the music player.").queue(); + return; + } + } + + if(b.getAudioPlayer().getPlayingTrack() != null && guild.getAudioManager().isConnected() && !guild.getAudioManager().getConnectedChannel().getMembers().contains(event.getMember())) { + tchannel.sendMessage("Music is already playing in a voice channel. Connect to " + + "that channel, then queue your song.").queue(); + 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(b,event.getAuthor().getId(), tchannel, false, searchPhrase, true)); + } + + 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/PowerCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/PowerCommand.java index 9b21f33..c153be3 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/PowerCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/PowerCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.Util; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/QueueCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/QueueCommand.java new file mode 100644 index 0000000..07fb349 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/QueueCommand.java @@ -0,0 +1,83 @@ +package com.fpghoti.biscuit.commands.client; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.audio.queue.AudioQueue; +import com.fpghoti.biscuit.audio.queue.QueuedTrack; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.MusicClientCommand; +import com.fpghoti.biscuit.util.Util; +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; + +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class QueueCommand extends MusicClientCommand{ + + public QueueCommand() { + name = "Queue"; + description = "Displays the upcoming songs in the music queue."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "queue [Page #]"; + minArgs = 0; + maxArgs = 1; + identifiers.add("queue"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + + Biscuit biscuit = Biscuit.getBiscuit(event.getGuild()); + biscuit.log(event.getAuthor().getName() + " issued a command: -queue"); + int pg = 1; + if (args.length > 0) { + if(Util.isDigit(args[0])) { + pg = Integer.parseInt(args[0]); + }else { + event.getTextChannel().sendMessage("Usage: ``" + usage + "``").queue(); + } + } + + AudioQueue queue = biscuit.getAudioScheduler().getQueue(); + + int pageCount = (int) Math.ceil((double) queue.size() / 8); + if (pg > pageCount) { + pg = pageCount; + } + + if(queue.size() == 0) { + if(biscuit.getAudioPlayer().getPlayingTrack() == null) { + event.getTextChannel().sendMessage("There is currently no song playing.").queue(); + }else { + event.getTextChannel().sendMessage("Nothing is queued to play after the current track.").queue(); + } + return; + } + + event.getTextChannel().sendMessage("**Use " + Main.getMainBiscuit().getProperties().getCommandSignifier() + "queue [Page #] to navigate the different pages.**").queue(); + event.getTextChannel().sendMessage("[" + Integer.toString(pg) + "/" + Integer.toString(pageCount) + "] ** Upcoming Music Tracks:**").queue(); + String msg = ""; + for (int i = 0; i < 8; i++) { + int index = (pg - 1) * 8 + i; + int count = index + 1; + String line = ""; + if (index < queue.size()) { + QueuedTrack track = queue.getTrack(index); + AudioTrack a = track.getTrack(); + Member m = track.getMember(); + line = "**" + count + ".** " + a.getInfo().title + " [" + Util.getTime(a.getInfo().length) + "]"; + if(m != null) { + line = line + " Added by: **" + m.getEffectiveName() + "**"; + } + } + if(!(index + 1 >= queue.size() || index == 7)) { + line = line + "\n"; + } + if (index < queue.size()) { + msg = msg + line; + } + } + event.getTextChannel().sendMessage(msg).queue(); + + } + + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/RecentSpammersCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/RecentSpammersCommand.java index 2e08e10..7bd90f7 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/RecentSpammersCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/RecentSpammersCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/SaveConfigCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/SaveConfigCommand.java index 40e810b..b370efe 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/SaveConfigCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/SaveConfigCommand.java @@ -6,7 +6,7 @@ import java.util.function.Consumer; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.logging.BColor; import com.fpghoti.biscuit.util.PermUtil; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/SkipCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/SkipCommand.java new file mode 100644 index 0000000..4918de8 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/SkipCommand.java @@ -0,0 +1,65 @@ +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 net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +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, MessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -skip"); + + if(b.getAudioPlayer().getPlayingTrack() == null) { + event.getChannel().sendMessage("There is not a song playing for you to skip!").queue(); + return; + } + + if(!event.getGuild().getAudioManager().getConnectedChannel().getMembers().contains(event.getMember())) { + event.getChannel().sendMessage("You need to be in the same voice channel in order to skip!").queue(); + return; + } + + if(b.getAudioScheduler().getVotes() >= (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() - 1) / 2) { + event.getChannel().sendMessage("Skip vote status: **[" + ( b.getAudioScheduler().getVotes() + 1) + "/" + + (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() - 1) + "]**" + + "\nSkipping current track.").queue(); + if(b.getAudioScheduler().getNextMessage() != null ) { + event.getChannel().sendMessage(b.getAudioScheduler().getNextMessage()).queue(); + } + b.getAudioScheduler().skip(); + return; + } + if(b.getAudioScheduler().voteSkip(event.getAuthor().getId())) { + event.getChannel().sendMessage("You voted to skip the current track.").queue(); + }else { + event.getChannel().sendMessage("You cannot vote to skip this track again." + + "\nSkip vote status: **[" + b.getAudioScheduler().getVotes() + "/" + + (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() - 1) + "]**").queue(); + } + + if(b.getAudioScheduler().getVotes() >= (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() - 1) / 2) { + event.getChannel().sendMessage("Skip vote status: **[" + b.getAudioScheduler().getVotes() + "/" + + event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() + "]**" + + "\nSkipping current track.").queue(); + if(b.getAudioScheduler().getNextMessage() != null ) { + event.getChannel().sendMessage(b.getAudioScheduler().getNextMessage()).queue(); + } + b.getAudioScheduler().skip(); + } + + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/SoftMuteCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/SoftMuteCommand.java index 600955f..d7c7c62 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/SoftMuteCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/SoftMuteCommand.java @@ -5,7 +5,7 @@ import java.util.function.Consumer; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.PermUtil; import net.dv8tion.jda.api.entities.Member; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/SquareRootCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/SquareRootCommand.java index 0b81422..9b6a7b6 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/SquareRootCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/SquareRootCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.Util; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/SubtractCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/SubtractCommand.java index 90f4448..a0f4ec6 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/SubtractCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/SubtractCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.Util; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/TogglePauseCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/TogglePauseCommand.java new file mode 100644 index 0000000..073c0d4 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/TogglePauseCommand.java @@ -0,0 +1,37 @@ +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.util.PermUtil; + +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class TogglePauseCommand extends MusicClientCommand{ + + public TogglePauseCommand() { + name = "Toggle Pause"; + description = "Toggles the pause status of the current track."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "togglepause"; + minArgs = 0; + maxArgs = 0; + identifiers.add("togglepause"); + identifiers.add("tp"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -togglepause"); + if(PermUtil.isMod(event.getMember())) { + if(b.getAudioPlayer().isPaused()) { + b.getAudioPlayer().setPaused(false); + event.getChannel().sendMessage("Unpaused the current track.").queue(); + }else { + b.getAudioPlayer().setPaused(true); + event.getChannel().sendMessage("Paused the current track.").queue(); + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/ToggleRoleCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/ToggleRoleCommand.java index 444fc69..366c0f5 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/ToggleRoleCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/ToggleRoleCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.PermUtil; import net.dv8tion.jda.api.entities.Emote; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/UIDCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/UIDCommand.java index 413c1e6..640af4f 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/UIDCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/UIDCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.PermUtil; import net.dv8tion.jda.api.entities.Member; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/UnSoftMuteCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/UnSoftMuteCommand.java index 50ef153..a9ba528 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/UnSoftMuteCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/UnSoftMuteCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.PermUtil; import net.dv8tion.jda.api.entities.Member; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/UnpauseCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/UnpauseCommand.java new file mode 100644 index 0000000..07d56cf --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/UnpauseCommand.java @@ -0,0 +1,35 @@ +package com.fpghoti.biscuit.commands.client; + +import com.fpghoti.biscuit.Main; +import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.base.ClientCommand; +import com.fpghoti.biscuit.util.PermUtil; + +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class UnpauseCommand extends ClientCommand{ + + public UnpauseCommand() { + name = "Unpause"; + description = "Unpauses the current track."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "unpause"; + minArgs = 0; + maxArgs = 0; + identifiers.add("unpause"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -unpause"); + if(PermUtil.isMod(event.getMember())) { + if(b.getAudioPlayer().isPaused()) { + b.getAudioPlayer().setPaused(false); + event.getChannel().sendMessage("Unpaused the current track.").queue(); + }else { + event.getChannel().sendMessage("The music player is not paused.").queue(); + } + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/WikiCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/WikiCommand.java index ba3aee9..947c66a 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/client/WikiCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/client/WikiCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.client; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ClientCommand; +import com.fpghoti.biscuit.commands.base.ClientCommand; import com.fpghoti.biscuit.util.PermUtil; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; diff --git a/src/main/java/com/fpghoti/biscuit/commands/client/WipeQueueCommand.java b/src/main/java/com/fpghoti/biscuit/commands/client/WipeQueueCommand.java new file mode 100644 index 0000000..fb85105 --- /dev/null +++ b/src/main/java/com/fpghoti/biscuit/commands/client/WipeQueueCommand.java @@ -0,0 +1,32 @@ +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.util.PermUtil; + +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; + +public class WipeQueueCommand extends MusicClientCommand{ + + public WipeQueueCommand() { + name = "Wipe Queue"; + description = "Removes all upcoming tracks from the queue."; + usage = Main.getMainBiscuit().getProperties().getCommandSignifier() + "wipequeue"; + minArgs = 0; + maxArgs = 0; + identifiers.add("wipequeue"); + identifiers.add("wipeq"); + } + + @Override + public void execute(String[] args, MessageReceivedEvent event) { + Biscuit b = Biscuit.getBiscuit(event.getGuild()); + b.log(event.getAuthor().getName() + " issued a command: -wipequeue"); + if(PermUtil.isMod(event.getMember())) { + b.getAudioScheduler().wipeQueue(); + event.getChannel().sendMessage("Removed upcoming songs from the music queue.").queue(); + } + } + +} diff --git a/src/main/java/com/fpghoti/biscuit/commands/console/GuildSayCommand.java b/src/main/java/com/fpghoti/biscuit/commands/console/GuildSayCommand.java index 5253110..f818a28 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/console/GuildSayCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/console/GuildSayCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.console; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ConsoleCommand; +import com.fpghoti.biscuit.commands.base.ConsoleCommand; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.TextChannel; diff --git a/src/main/java/com/fpghoti/biscuit/commands/console/SayCommand.java b/src/main/java/com/fpghoti/biscuit/commands/console/SayCommand.java index 0708575..c825b5e 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/console/SayCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/console/SayCommand.java @@ -2,7 +2,7 @@ package com.fpghoti.biscuit.commands.console; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.biscuit.Biscuit; -import com.fpghoti.biscuit.commands.ConsoleCommand; +import com.fpghoti.biscuit.commands.base.ConsoleCommand; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.TextChannel; diff --git a/src/main/java/com/fpghoti/biscuit/commands/console/ShutdownConsoleCommand.java b/src/main/java/com/fpghoti/biscuit/commands/console/ShutdownConsoleCommand.java index b3efbad..0f17438 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/console/ShutdownConsoleCommand.java +++ b/src/main/java/com/fpghoti/biscuit/commands/console/ShutdownConsoleCommand.java @@ -1,7 +1,7 @@ package com.fpghoti.biscuit.commands.console; import com.fpghoti.biscuit.Main; -import com.fpghoti.biscuit.commands.ConsoleCommand; +import com.fpghoti.biscuit.commands.base.ConsoleCommand; public class ShutdownConsoleCommand extends ConsoleCommand{ diff --git a/src/main/java/com/fpghoti/biscuit/config/BiscuitConfig.java b/src/main/java/com/fpghoti/biscuit/config/BiscuitConfig.java index 2406c59..d84cf90 100644 --- a/src/main/java/com/fpghoti/biscuit/config/BiscuitConfig.java +++ b/src/main/java/com/fpghoti/biscuit/config/BiscuitConfig.java @@ -132,6 +132,8 @@ public class BiscuitConfig { if(isMain) { added = addProperty("Command-Signifier", "-", prop, added, silent); added = addProperty("Bot-Token", "", prop, added, silent); + added = addProperty("Enable-Music-Bot", "true", prop, added, silent); + added = addProperty("Log-Music-Player", "true", prop, added, silent); } added = addProperty("Guild-Identifier", name, prop, added, silent); @@ -175,6 +177,8 @@ public class BiscuitConfig { added = addProperty("Custom-Command-Names", "", prop, added, silent); added = addProperty("DM-Before-Kick", "true", prop, added, silent); added = addProperty("Kick-DM-Invite", "", prop, added, silent); + added = addProperty("Allow-Music-Bot", "true", prop, added, silent); + added = addProperty("Music-Channels", "", 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 d95cedf..74fcadd 100644 --- a/src/main/java/com/fpghoti/biscuit/config/BiscuitProperties.java +++ b/src/main/java/com/fpghoti/biscuit/config/BiscuitProperties.java @@ -22,6 +22,28 @@ public class BiscuitProperties { return Main.getMainBiscuit().getConfig().getFromConfig(key, Main.getMainBiscuit()); } + public boolean musicBotEnabled(){ + String key = "Enable-Music-Bot"; + return Main.getMainBiscuit().getConfig().getFromConfig(key, Main.getMainBiscuit()).equalsIgnoreCase("true"); + } + + public boolean logMusicPlayer(){ + String key = "Log-Music-Player"; + return Main.getMainBiscuit().getConfig().getFromConfig(key, Main.getMainBiscuit()).equalsIgnoreCase("true"); + } + + public boolean allowMusicBot(){ + if(!musicBotEnabled()) { + return false; + } + String key = "Allow-Music-Bot"; + if(biscuit.getConfig().getFromConfig(key, biscuit).equalsIgnoreCase("[global]") && biscuit.getGuild() != null) { + return Main.getMainBiscuit().getProperties().allowMusicBot(); + } + String value = biscuit.getConfig().getFromConfig(key, biscuit); + return value.equalsIgnoreCase("true"); + } + public String getGuildCode(){ String key = "Guild-Code"; if(biscuit.getGuild() == null) { @@ -268,6 +290,19 @@ public class BiscuitProperties { return list; } + public String[] getMusicChannels(){ + String key = "Music-Channels"; + if(biscuit.getConfig().getFromConfig(key, biscuit).equalsIgnoreCase("[global]") && biscuit.getGuild() != null) { + return Main.getMainBiscuit().getProperties().getMusicChannels(); + } + String [] list = biscuit.getConfig().getFromConfig(key, biscuit).replace(" , ", ",").replace(", ", ",").split(","); + if(list.length == 1 && list[0].equals("")) { + String[] blank = {}; + return blank; + } + return list; + } + public String[] blockedUnicodeEmotes(){ String key = "Block-Unicode-Emotes"; if(biscuit.getConfig().getFromConfig(key, biscuit).equalsIgnoreCase("[global]") && biscuit.getGuild() != null) { diff --git a/src/main/java/com/fpghoti/biscuit/commands/CommandListener.java b/src/main/java/com/fpghoti/biscuit/listener/CommandListener.java similarity index 92% rename from src/main/java/com/fpghoti/biscuit/commands/CommandListener.java rename to src/main/java/com/fpghoti/biscuit/listener/CommandListener.java index ca47cf4..ef37d2c 100644 --- a/src/main/java/com/fpghoti/biscuit/commands/CommandListener.java +++ b/src/main/java/com/fpghoti/biscuit/listener/CommandListener.java @@ -1,8 +1,9 @@ -package com.fpghoti.biscuit.commands; +package com.fpghoti.biscuit.listener; import java.util.Scanner; import com.fpghoti.biscuit.biscuit.Biscuit; +import com.fpghoti.biscuit.commands.CommandManager; import com.fpghoti.biscuit.logging.BiscuitLog; import com.fpghoti.biscuit.util.PermUtil; diff --git a/src/main/java/com/fpghoti/biscuit/listener/MessageReceiveListener.java b/src/main/java/com/fpghoti/biscuit/listener/MessageReceiveListener.java index ed9234b..ff50e09 100644 --- a/src/main/java/com/fpghoti/biscuit/listener/MessageReceiveListener.java +++ b/src/main/java/com/fpghoti/biscuit/listener/MessageReceiveListener.java @@ -9,56 +9,53 @@ import com.fpghoti.biscuit.logging.BColor; import com.fpghoti.biscuit.util.ChatFilter; import com.fpghoti.biscuit.util.PermUtil; import com.fpghoti.biscuit.util.Util; -import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message.Attachment; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; public class MessageReceiveListener extends ListenerAdapter{ @Override - public void onMessageReceived(MessageReceivedEvent event){ - if (event.isFromType(ChannelType.TEXT)) { - Biscuit biscuit = Biscuit.getBiscuit(event.getGuild()); - if(event.getAuthor().isBot()) { - logBot(event, biscuit); - return; - } - PermUtil.clearUndeservedRoles(event.getMember()); + public void onGuildMessageReceived(GuildMessageReceivedEvent event){ + Biscuit biscuit = Biscuit.getBiscuit(event.getGuild()); + if(event.getAuthor().isBot()) { + logBot(event, biscuit); + return; + } + PermUtil.clearUndeservedRoles(event.getMember()); - logUser(event, biscuit); + logUser(event, biscuit); - if(isNaughty(event)) { - return; - } + if(isNaughty(event)) { + return; + } - if(handleSoftmuted(event, biscuit)) { - return; - } - if(!handleSpammer(event, biscuit) && biscuit.getProperties().spamPunishAllow()){ - checkNewSpammer(event, biscuit); - } + if(handleSoftmuted(event, biscuit)) { + return; + } + if(!handleSpammer(event, biscuit) && biscuit.getProperties().spamPunishAllow()){ + checkNewSpammer(event, biscuit); } } - private void logBot(MessageReceivedEvent event, Biscuit biscuit) { - if(Util.isLoggable(event.getTextChannel())) { + private void logBot(GuildMessageReceivedEvent event, Biscuit biscuit) { + if(Util.isLoggable(event.getChannel())) { if(biscuit.getProperties().logChat()) { biscuit.log("[" + BColor.BLACK_BOLD + "BOT" + BColor.RESET + "] [" + BColor.RED + "#" + event.getChannel().getName() + BColor.RESET + "] " - + BColor.RED_BOLD + event.getAuthor().getName() + ": " + BColor.RESET + event.getMessage().getContentDisplay()); + + BColor.RED_BOLD + event.getAuthor().getName() + ": " + BColor.RESET + event.getMessage().getContentDisplay()); } } } - - private void logUser(MessageReceivedEvent event, Biscuit biscuit) { - if(Util.isLoggable(event.getTextChannel())) { + + private void logUser(GuildMessageReceivedEvent event, Biscuit biscuit) { + if(Util.isLoggable(event.getChannel())) { if(biscuit.getProperties().logChat()) { biscuit.log("[" + BColor.CYAN_BOLD + "MSG" + BColor.RESET + "] " + BColor.GREEN + "ID: " + BColor.RESET + event.getMessageId() + BColor.GREEN + " Sender: " + BColor.RESET + event.getAuthor().getAsMention() + BColor.GREEN + " Channel: " + BColor.RESET + event.getChannel().getName()); String msg = event.getMessage().getContentDisplay(); - + if(event.getMessage().getAttachments().size() >= 1) { String tail = BColor.CYAN + "[ATTACHMENT(S)]: "; if(!msg.equals("")) { @@ -69,16 +66,16 @@ public class MessageReceiveListener extends ListenerAdapter{ } msg = msg + tail; } - + biscuit.log(BColor.GREEN_BOLD + event.getAuthor().getName() + ": " + BColor.WHITE_BOLD + msg); } } } - private boolean isNaughty(MessageReceivedEvent event) { + private boolean isNaughty(GuildMessageReceivedEvent event) { // TODO make staff filter configurable if(!event.getChannel().getName().toLowerCase().contains("staff") && ChatFilter.filter(event, false)){ - event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + " This message contains words not appropriate for this channel.").queue(new Consumer() + event.getChannel().sendMessage(event.getAuthor().getAsMention() + " This message contains words not appropriate for this channel.").queue(new Consumer() { @Override public void accept(Message msg){ @@ -91,7 +88,7 @@ public class MessageReceiveListener extends ListenerAdapter{ return false; } - private boolean handleSpammer(MessageReceivedEvent event, Biscuit biscuit) { + private boolean handleSpammer(GuildMessageReceivedEvent event, Biscuit biscuit) { //TODO make numbers configurable BiscuitMessageStore store = biscuit.getMessageStore(); String mention = event.getAuthor().getAsMention(); @@ -113,7 +110,7 @@ public class MessageReceiveListener extends ListenerAdapter{ return false; } - private boolean handleSoftmuted(MessageReceivedEvent event, Biscuit biscuit) { + private boolean handleSoftmuted(GuildMessageReceivedEvent event, Biscuit biscuit) { //TODO make numbers configurable BiscuitMessageStore store = biscuit.getMessageStore(); String mention = event.getAuthor().getAsMention(); @@ -135,7 +132,7 @@ public class MessageReceiveListener extends ListenerAdapter{ return false; } - private void checkNewSpammer(MessageReceivedEvent event, Biscuit biscuit) { + private void checkNewSpammer(GuildMessageReceivedEvent event, Biscuit biscuit) { BiscuitMessageStore store = biscuit.getMessageStore(); String mention = event.getAuthor().getAsMention(); @@ -152,7 +149,7 @@ public class MessageReceiveListener extends ListenerAdapter{ store.addSpammer(event.getAuthor()); store.removeSpamWarned(event.getAuthor()); event.getMessage().delete().submit(); - event.getTextChannel().sendMessage("*Flagging " + mention + " as spam!*").queue(new Consumer() + event.getChannel().sendMessage("*Flagging " + mention + " as spam!*").queue(new Consumer() { @Override public void accept(Message msg){ @@ -165,7 +162,7 @@ public class MessageReceiveListener extends ListenerAdapter{ }else if(!store.isSpammer(event.getAuthor()) && !store.isSpamWarned(event.getAuthor())){ store.removeMessageCount(event.getAuthor()); store.addSpamWarned(event.getAuthor()); - event.getTextChannel().sendMessage("**STOP spamming, " + mention + "! You have been warned!**").queue(new Consumer() + event.getChannel().sendMessage("**STOP spamming, " + mention + "! You have been warned!**").queue(new Consumer() { @Override public void accept(Message msg){ diff --git a/src/main/java/com/fpghoti/biscuit/util/ChatFilter.java b/src/main/java/com/fpghoti/biscuit/util/ChatFilter.java index 9098268..1227b2f 100644 --- a/src/main/java/com/fpghoti/biscuit/util/ChatFilter.java +++ b/src/main/java/com/fpghoti/biscuit/util/ChatFilter.java @@ -5,17 +5,17 @@ import com.fpghoti.biscuit.logging.BColor; import com.vdurmont.emoji.EmojiParser; import net.dv8tion.jda.api.entities.Emote; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; public class ChatFilter { public static String[] suffixes = {"ing","s","ed","er","es","y","ers","ier","iest","ies","ys"}; - public static boolean filter(MessageReceivedEvent event) { + public static boolean filter(GuildMessageReceivedEvent event) { return filter(event, true); } - public static boolean filter(MessageReceivedEvent event, boolean silent) { + public static boolean filter(GuildMessageReceivedEvent event, boolean silent) { Biscuit biscuit = Biscuit.getBiscuit(event.getGuild()); String msg = event.getMessage().getContentDisplay(); diff --git a/src/main/java/com/fpghoti/biscuit/util/Util.java b/src/main/java/com/fpghoti/biscuit/util/Util.java index 70653b4..d66918f 100644 --- a/src/main/java/com/fpghoti/biscuit/util/Util.java +++ b/src/main/java/com/fpghoti/biscuit/util/Util.java @@ -59,5 +59,23 @@ public class Util { } return s2.replace(".", "").matches("[0-9]+"); } + + public static String getTime(long t) { + long rawseconds = Math.round(t / 1000); + long rawminutes = Math.round(rawseconds/60); + long hour = Math.round(rawminutes/60); + long minute = rawminutes - (hour * 60); + long second = rawseconds - (rawminutes * 60); + if(hour < 0) { + hour = 0; + } + if(minute < 0) { + minute = 0; + } + if(second <= 1) { + second = 2; + } + return String.format("%02d:%02d:%02d", hour, minute, second - 1); + } } diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties index a701f1b..307ab86 100644 --- a/src/main/resources/config.properties +++ b/src/main/resources/config.properties @@ -99,6 +99,27 @@ DM-Before-Kick = true #Use full link Kick-DM-Invite = +#Enable Music Bot functionality. +#This command is for the bot admin only. If disabled, no guild +#Will be allowed to enable and use the Music bot commands. +Enable-Music-Bot = true + +#Individual guild owners can enable/disable this to allow/disallow +#Music bot features in their server. Defaults to the setting +#Set in the main config.properties. This will do nothing if +#Enable-Music-Bot is already set to false. +Allow-Music-Bot = true + +#This logs music player events to the terminal. +#The music player logs may be annoyance. Disable them here. +#Errors will still be logged. +Log-Music-Player = true + +#To restrict music to certain channels, add them here. +#i.e: +#Music-Channels = Room 1, Room 2 +Music-Channels = + #List your custom commands here. This line will always generate blank. #Example - Custom-Command-Names = hello,botcheck,apple Custom-Command-Names =