From f373b5e9692318f8dc2a5eb8a2c5c6f60c041c2a Mon Sep 17 00:00:00 2001 From: GregTCLTK Date: Sun, 22 Dec 2019 16:47:37 +0100 Subject: [PATCH] Music pre-release!!! --- .../java/com/bbn/hadder/audio/AudioInfo.java | 28 +++++ .../com/bbn/hadder/audio/AudioManager.java | 100 ++++++++++++++++ .../com/bbn/hadder/audio/TrackManager.java | 73 ++++++++++++ .../hadder/commands/music/PlayCommand.java | 109 ++++++++++++++++++ .../hadder/commands/music/StopCommand.java | 12 +- 5 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/bbn/hadder/audio/AudioInfo.java create mode 100644 src/main/java/com/bbn/hadder/audio/TrackManager.java create mode 100644 src/main/java/com/bbn/hadder/commands/music/PlayCommand.java diff --git a/src/main/java/com/bbn/hadder/audio/AudioInfo.java b/src/main/java/com/bbn/hadder/audio/AudioInfo.java new file mode 100644 index 0000000..8aa35e9 --- /dev/null +++ b/src/main/java/com/bbn/hadder/audio/AudioInfo.java @@ -0,0 +1,28 @@ +package com.bbn.hadder.audio; + +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import net.dv8tion.jda.api.entities.Member; + +/** + * @author Skidder / GregTCLTK + */ + +public class AudioInfo { + + private final AudioTrack track; + private final Member author; + + AudioInfo(AudioTrack track, Member author) { + this.track = track; + this.author = author; + } + + public AudioTrack getTrack() { + return track; + } + + public Member getAuthor() { + return author; + } + +} diff --git a/src/main/java/com/bbn/hadder/audio/AudioManager.java b/src/main/java/com/bbn/hadder/audio/AudioManager.java index b133dca..60db2f8 100644 --- a/src/main/java/com/bbn/hadder/audio/AudioManager.java +++ b/src/main/java/com/bbn/hadder/audio/AudioManager.java @@ -1,9 +1,109 @@ package com.bbn.hadder.audio; +import com.bbn.hadder.commands.CommandEvent; +import com.bbn.hadder.utils.MessageEditor; +import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; +import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Message; + +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + /** * @author Skidder / GregTCLTK */ public class AudioManager { + public static final Map> players = new HashMap<>(); + public static final AudioPlayerManager myManager = new DefaultAudioPlayerManager(); + + public static void loadTrack(String identifier, CommandEvent event, Message msg) { + + Guild guild = event.getGuild(); + AudioManager.getPlayer(guild); + + myManager.loadItemOrdered(guild, identifier, new AudioLoadResultHandler() { + + @Override + public void trackLoaded(AudioTrack track) { + AudioManager.getTrackManager(guild).queue(track, event.getMember()); + msg.editMessage(event.getMessageEditor().getMessage(MessageEditor.MessageType.INFO, + "commands.music.play.success.loading.title", "⏯", + "", "") + .addField(event.getMessageEditor().getTerm("commands.music.play.success.title"), track.getInfo().title, false) + .addField(event.getMessageEditor().getTerm("commands.music.play.success.author"), track.getInfo().author, true) + .addField(event.getMessageEditor().getTerm("commands.music.play.success.length"), + String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(track.getInfo().length), + TimeUnit.MILLISECONDS.toMinutes(track.getInfo().length) % TimeUnit.HOURS.toMinutes(1), + TimeUnit.MILLISECONDS.toSeconds(track.getInfo().length) % TimeUnit.MINUTES.toSeconds(1)), true) + .build()).queue(); + } + + @Override + public void playlistLoaded(AudioPlaylist playlist) { + if (playlist.getSelectedTrack() != null) { + trackLoaded(playlist.getSelectedTrack()); + } else if (playlist.isSearchResult()) { + trackLoaded(playlist.getTracks().get(0)); + } else { + for (int i = 0; i < Math.min(playlist.getTracks().size(), 200); i++) { + AudioManager.getTrackManager(guild).queue(playlist.getTracks().get(i), event.getMember()); + } + } + } + + @Override + public void noMatches() { + msg.editMessage(event.getMessageEditor().getMessage(MessageEditor.MessageType.INFO, + "commands.music.play.error.match.title", "❌", + "commands.music.play.error.match.description", "") + .build()).queue(); + } + + @Override + public void loadFailed(FriendlyException e) { + msg.editMessage(event.getMessageEditor().getMessage(MessageEditor.MessageType.INFO, + "commands.music.play.error.load.title", "❌", + "commands.music.play.error.load.description", "") + .build()).queue(); + } + }); + } + + public static boolean hasPlayer(Guild guild) { + return players.containsKey(guild.getId()); + } + + public static AudioPlayer getPlayer(Guild guild) { + AudioPlayer p; + if (hasPlayer(guild)) { + p = players.get(guild.getId()).getKey(); + } else { + p = createPlayer(guild); + } + return p; + } + + public static TrackManager getTrackManager(Guild guild) { + return players.get(guild.getId()).getValue(); + } + + public static AudioPlayer createPlayer(Guild guild) { + AudioPlayer nPlayer = myManager.createPlayer(); + TrackManager manager = new TrackManager(nPlayer); + nPlayer.addListener(manager); + guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(nPlayer)); + players.put(guild.getId(), new AbstractMap.SimpleEntry<>(nPlayer, manager)); + return nPlayer; + } + } diff --git a/src/main/java/com/bbn/hadder/audio/TrackManager.java b/src/main/java/com/bbn/hadder/audio/TrackManager.java new file mode 100644 index 0000000..b4c1e9a --- /dev/null +++ b/src/main/java/com/bbn/hadder/audio/TrackManager.java @@ -0,0 +1,73 @@ +package com.bbn.hadder.audio; + +import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; +import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter; +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.VoiceChannel; + +import java.util.*; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * @author Skidder / GregTCLTK + */ + +public class TrackManager extends AudioEventAdapter { + + private final AudioPlayer player; + private final Queue queue; + + public TrackManager(AudioPlayer player) { + this.player = player; + this.queue = new LinkedBlockingQueue<>(); + } + + public void queue(AudioTrack track, Member author) { + AudioInfo info = new AudioInfo(track, author); + queue.add(info); + + if (player.getPlayingTrack() == null) { + player.playTrack(track); + } + } + + @Override + public void onTrackStart(AudioPlayer player, AudioTrack track) { + AudioInfo info = queue.element(); + VoiceChannel vChan = info.getAuthor().getVoiceState().getChannel(); + if (vChan == null) { + player.stopTrack(); + } else { + info.getAuthor().getGuild().getAudioManager().openAudioConnection(vChan); + } + } + + @Override + public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { + Guild g = queue.poll().getAuthor().getGuild(); + if (queue.isEmpty()) { + g.getAudioManager().closeAudioConnection(); + } else { + player.playTrack(queue.element().getTrack()); + } + } + + public Set getQueuedTracks() { + return new LinkedHashSet<>(queue); + } + + public void purgeQueue() { + queue.clear(); + } + + public void remove(AudioInfo entry) { + queue.remove(entry); + } + + public AudioInfo getTrackInfo(AudioTrack track) { + return queue.stream().filter(audioInfo -> audioInfo.getTrack().equals(track)).findFirst().orElse(null); + } +} diff --git a/src/main/java/com/bbn/hadder/commands/music/PlayCommand.java b/src/main/java/com/bbn/hadder/commands/music/PlayCommand.java new file mode 100644 index 0000000..9e34f3e --- /dev/null +++ b/src/main/java/com/bbn/hadder/commands/music/PlayCommand.java @@ -0,0 +1,109 @@ +package com.bbn.hadder.commands.music; + +import com.bbn.hadder.audio.AudioInfo; +import com.bbn.hadder.audio.AudioManager; +import com.bbn.hadder.audio.AudioPlayerSendHandler; +import com.bbn.hadder.audio.TrackManager; +import com.bbn.hadder.commands.Command; +import com.bbn.hadder.commands.CommandEvent; +import com.bbn.hadder.utils.MessageEditor; +import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; +import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; +import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Message; + +import java.net.URL; +import java.sql.Timestamp; +import java.util.*; +import java.util.concurrent.TimeUnit; + +import static com.bbn.hadder.audio.AudioManager.myManager; + +/** + * @author Skidder / GregTCLTK + */ + +public class PlayCommand implements Command { + + /* + private static final String CD = "\uD83D\uDCBF"; + private static final String MIC = "\uD83C\uDFA4 **|>** "; */ + + @Override + public void executed(String[] args, CommandEvent event) { + if (args.length > 0) { + if (event.getMember().getVoiceState().inVoiceChannel()) { + String input = event.getMessage().getContentRaw().replaceFirst(event.getRethink().getGuildPrefix(event.getGuild().getId()) + "play ", "").replaceFirst(event.getRethink().getUserPrefix(event.getAuthor().getId()) + "play ", ""); + try { + new URL(input).toURI(); + Message msg = event.getTextChannel().sendMessage(event.getMessageEditor().getMessage(MessageEditor.MessageType.INFO, + "commands.music.play.load.title", "⭕", + "commands.music.play.load.description", "").build()).complete(); + AudioManager.loadTrack(input, event, msg); + } catch (Exception ignore) { + Message msg = event.getTextChannel().sendMessage(event.getMessageEditor().getMessage(MessageEditor.MessageType.INFO, + "commands.music.play.load.title", "⏯", + "commands.music.play.load.description", "").build()).complete(); + AudioManager.loadTrack("ytsearch: " + input, event, msg); + } + } else { + event.getTextChannel().sendMessage(event.getMessageEditor().getMessage( + MessageEditor.MessageType.WARNING, + "commands.music.join.error.channel.title", + "commands.music.join.error.channel.description") + .build()).queue(); + } + } else event.getHelpCommand().sendHelp(this, event); + + /* OUTSOURCE THIS + Guild guild = event.getGuild(); + if (args.length == 1) { + switch (args[0].toLowerCase()) { + case "info": + if (!hasPlayer(guild) || getPlayer(guild).getPlayingTrack() == null) { // No song is playing + event.getTextChannel().sendMessage("No song is being played at the moment! *It's your time to shine..*").queue(); + } else { + AudioTrack track = getPlayer(guild).getPlayingTrack(); + event.getTextChannel().sendMessage("Track Info" + String.format(QUEUE_DESCRIPTION, CD, getOrNull(track.getInfo().title), + "\n\u23F1 **|>** `[ " + getTimestamp(track.getPosition()) + " / " + getTimestamp(track.getInfo().length) + " ]`", + "\n" + MIC, getOrNull(track.getInfo().author), + "\n\uD83C\uDFA7 **|>** " + "")).queue(); + } + break; + + case "queue": + if (!hasPlayer(guild) || getTrackManager(guild).getQueuedTracks().isEmpty()) { + event.getTextChannel().sendMessage("The queue is empty! Load a song with **" + + "dd" + "music play**!").queue(); + } else { + StringBuilder sb = new StringBuilder(); + Set queue = getTrackManager(guild).getQueuedTracks(); + queue.forEach(audioInfo -> sb.append(buildQueueMessage(audioInfo))); + } + break; + } + } */ + + } + + @Override + public String[] labels() { + return new String[]{"play"}; + } + + @Override + public String description() { + return "commands.music.play.help.description"; + } + + @Override + public String usage() { + return "song"; + } +} diff --git a/src/main/java/com/bbn/hadder/commands/music/StopCommand.java b/src/main/java/com/bbn/hadder/commands/music/StopCommand.java index da77b5e..1adeb88 100644 --- a/src/main/java/com/bbn/hadder/commands/music/StopCommand.java +++ b/src/main/java/com/bbn/hadder/commands/music/StopCommand.java @@ -1,7 +1,9 @@ package com.bbn.hadder.commands.music; +import com.bbn.hadder.audio.AudioManager; import com.bbn.hadder.commands.Command; import com.bbn.hadder.commands.CommandEvent; +import com.bbn.hadder.utils.MessageEditor; /** * @author Skidder / GregTCLTK @@ -11,7 +13,13 @@ public class StopCommand implements Command { @Override public void executed(String[] args, CommandEvent event) { - + AudioManager.players.remove(event.getGuild().getId()); + AudioManager.getPlayer(event.getGuild()).destroy(); + AudioManager.getTrackManager(event.getGuild()).purgeQueue(); + event.getGuild().getAudioManager().closeAudioConnection(); + event.getTextChannel().sendMessage(event.getMessageEditor().getMessage(MessageEditor.MessageType.INFO, + "commands.music.stop.success.title", + "commands.music.stop.success.description").build()).queue(); } @Override @@ -21,7 +29,7 @@ public class StopCommand implements Command { @Override public String description() { - return "Stops the song"; + return "commands.music.stop.help.description"; } @Override