diff --git a/pom.xml b/pom.xml
index 7346825..dbf03e6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
net.dv8tion
JDA
- 4.0.0_79
+ 4.1.0_81
org.json
diff --git a/src/main/java/com/bbn/hadder/Hadder.java b/src/main/java/com/bbn/hadder/Hadder.java
index f96792f..f89a23c 100644
--- a/src/main/java/com/bbn/hadder/Hadder.java
+++ b/src/main/java/com/bbn/hadder/Hadder.java
@@ -57,6 +57,7 @@ public class Hadder {
new RebootCommand(),
new EqualsCommand(),
new InviteCommand(),
+ new ScreenShareCommand(),
new NickCommand(),
new PrefixCommand(),
new BlowjobCommand(),
@@ -88,7 +89,11 @@ public class Hadder {
new AboutCommand(),
new LanguageCommand(),
new ClydeCommand(),
- new StarBoardCommand()), config, helpCommand);
+ new PlayCommand(),
+ new StarBoardCommand(),
+ new QueueCommand(),
+ new InfoCommand(),
+ new StopCommand()), config, helpCommand);
builder.addEventListeners(
new MentionListener(rethink),
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
new file mode 100644
index 0000000..7c0d6dd
--- /dev/null
+++ b/src/main/java/com/bbn/hadder/audio/AudioManager.java
@@ -0,0 +1,118 @@
+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.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.util.AbstractMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Skidder / GregTCLTK
+ */
+
+public class AudioManager {
+
+ public AudioManager() {
+ AudioSourceManagers.registerRemoteSources(myManager);
+ }
+
+ public final Map> players = new HashMap<>();
+ public final AudioPlayerManager myManager = new DefaultAudioPlayerManager();
+
+ public void loadTrack(String identifier, CommandEvent event, Message msg) {
+
+ Guild guild = event.getGuild();
+ getPlayer(guild);
+
+ myManager.loadItemOrdered(guild, identifier, new AudioLoadResultHandler() {
+
+ @Override
+ public void trackLoaded(AudioTrack track) {
+ 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++) {
+ 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 boolean hasPlayer(Guild guild) {
+ return players.containsKey(guild.getId());
+ }
+
+ public AudioPlayer getPlayer(Guild guild) {
+ AudioPlayer p;
+ if (hasPlayer(guild)) {
+ p = players.get(guild.getId()).getKey();
+ } else {
+ p = createPlayer(guild);
+ }
+ return p;
+ }
+
+ public TrackManager getTrackManager(Guild guild) {
+ return players.get(guild.getId()).getValue();
+ }
+
+ public 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;
+ }
+
+ public String getOrNull(String s) {
+ return s.isEmpty() ? "N/A" : s;
+ }
+
+}
diff --git a/src/main/java/com/bbn/hadder/audio/AudioPlayerSendHandler.java b/src/main/java/com/bbn/hadder/audio/AudioPlayerSendHandler.java
new file mode 100644
index 0000000..1863de2
--- /dev/null
+++ b/src/main/java/com/bbn/hadder/audio/AudioPlayerSendHandler.java
@@ -0,0 +1,49 @@
+package com.bbn.hadder.audio;
+
+import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
+import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
+import net.dv8tion.jda.api.audio.AudioSendHandler;
+
+import javax.annotation.Nullable;
+import java.nio.ByteBuffer;
+
+/**
+ * @author Skidder / GregTCLTK
+ */
+
+public class AudioPlayerSendHandler implements AudioSendHandler {
+
+ private final AudioPlayer audioPlayer;
+ private AudioFrame lastFrame;
+
+ public AudioPlayerSendHandler(AudioPlayer audioPlayer) {
+ this.audioPlayer = audioPlayer;
+ }
+
+ @Override
+ public boolean canProvide() {
+ if (lastFrame == null) {
+ lastFrame = audioPlayer.provide();
+ }
+
+ return lastFrame != null;
+ }
+
+ @Nullable
+ @Override
+ public ByteBuffer provide20MsAudio() {
+ if (lastFrame == null) {
+ lastFrame = audioPlayer.provide();
+ }
+
+ byte[] data = lastFrame != null ? lastFrame.getData() : null;
+ lastFrame = null;
+
+ return ByteBuffer.wrap(data);
+ }
+
+ @Override
+ public boolean isOpus() {
+ return true;
+ }
+}
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/general/AboutCommand.java b/src/main/java/com/bbn/hadder/commands/general/AboutCommand.java
index 82d17eb..3800836 100644
--- a/src/main/java/com/bbn/hadder/commands/general/AboutCommand.java
+++ b/src/main/java/com/bbn/hadder/commands/general/AboutCommand.java
@@ -24,7 +24,7 @@ public class AboutCommand implements Command {
@Override
public String[] labels() {
- return new String[]{"about", "info"};
+ return new String[]{"about"};
}
@Override
diff --git a/src/main/java/com/bbn/hadder/commands/moderation/StarBoardCommand.java b/src/main/java/com/bbn/hadder/commands/moderation/StarBoardCommand.java
index 50d6987..3371eec 100644
--- a/src/main/java/com/bbn/hadder/commands/moderation/StarBoardCommand.java
+++ b/src/main/java/com/bbn/hadder/commands/moderation/StarBoardCommand.java
@@ -14,7 +14,7 @@ public class StarBoardCommand implements Command {
event.getChannel().sendMessage(
event.getMessageEditor().getMessage(
MessageEditor.MessageType.INFO,
- "commands.moderation.starboard.successchannel","")
+ "commands.moderation.starboard.success.title","")
.build())
.queue();
} else {
diff --git a/src/main/java/com/bbn/hadder/commands/music/InfoCommand.java b/src/main/java/com/bbn/hadder/commands/music/InfoCommand.java
new file mode 100644
index 0000000..85605b3
--- /dev/null
+++ b/src/main/java/com/bbn/hadder/commands/music/InfoCommand.java
@@ -0,0 +1,57 @@
+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.sedmelluq.discord.lavaplayer.track.AudioTrack;
+
+/**
+ * @author Skidder / GregTCLTK
+ */
+
+public class InfoCommand implements Command {
+
+ private static final String CD = "\uD83D\uDCBF";
+ private static final String MIC = "\uD83C\uDFA4";
+
+ private static final String QUEUE_TITLE = "__%s has added %d new track%s to the Queue:__";
+ private static final String QUEUE_DESCRIPTION = "%s **|>** %s\n%s\n%s %s\n%s";
+ private static final String QUEUE_INFO = "Info about the Queue: (Size - %d)";
+ private static final String ERROR = "Error while loading \"%s\"";
+ @Override
+ public void executed(String[] args, CommandEvent event) {
+ if (!new AudioManager().hasPlayer(event.getGuild()) || new AudioManager().getPlayer(event.getGuild()).getPlayingTrack() == null) {
+ event.getTextChannel().sendMessage("No song is being played at the moment! *It's your time to shine..*").queue();
+ } else {
+ AudioTrack track = new AudioManager().getPlayer(event.getGuild()).getPlayingTrack();
+ event.getTextChannel().sendMessage("Track Info" + String.format(QUEUE_DESCRIPTION, CD, new AudioManager().getOrNull(track.getInfo().title),
+ "\n\u23F1 **|>** `[ " + getTimestamp(track.getPosition()) + " / " + getTimestamp(track.getInfo().length) + " ]`",
+ "\n" + MIC, new AudioManager().getOrNull(track.getInfo().author),
+ "\n\uD83C\uDFA7 **|>** " + "")).queue();
+ }
+ }
+
+ private String getTimestamp(long milis) {
+ long seconds = milis / 1000;
+ long hours = Math.floorDiv(seconds, 3600);
+ seconds = seconds - (hours * 3600);
+ long mins = Math.floorDiv(seconds, 60);
+ seconds = seconds - (mins * 60);
+ return (hours == 0 ? "" : hours + ":") + String.format("%02d", mins) + ":" + String.format("%02d", seconds);
+ }
+
+ @Override
+ public String[] labels() {
+ return new String[]{"info"};
+ }
+
+ @Override
+ public String description() {
+ return "Shows information about the playing song";
+ }
+
+ @Override
+ public String usage() {
+ return "";
+ }
+}
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..ddb5c92
--- /dev/null
+++ b/src/main/java/com/bbn/hadder/commands/music/PlayCommand.java
@@ -0,0 +1,58 @@
+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;
+import net.dv8tion.jda.api.entities.Message;
+
+import java.net.URL;
+
+/**
+ * @author Skidder / GregTCLTK
+ */
+
+public class PlayCommand implements Command {
+
+ @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();
+ new 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();
+ new 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);
+ }
+
+ @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/QueueCommand.java b/src/main/java/com/bbn/hadder/commands/music/QueueCommand.java
new file mode 100644
index 0000000..d2178f9
--- /dev/null
+++ b/src/main/java/com/bbn/hadder/commands/music/QueueCommand.java
@@ -0,0 +1,52 @@
+package com.bbn.hadder.commands.music;
+
+import com.bbn.hadder.audio.AudioInfo;
+import com.bbn.hadder.audio.AudioManager;
+import com.bbn.hadder.commands.Command;
+import com.bbn.hadder.commands.CommandEvent;
+import com.bbn.hadder.utils.MessageEditor;
+import net.dv8tion.jda.api.EmbedBuilder;
+
+import java.util.Set;
+
+/**
+ * @author Skidder / GregTCLTK
+ */
+
+public class QueueCommand implements Command {
+
+ @Override
+ public void executed(String[] args, CommandEvent event) {
+ if (!new AudioManager().hasPlayer(event.getGuild()) || new AudioManager().getTrackManager(event.getGuild()).getQueuedTracks().isEmpty()) {
+ event.getTextChannel().sendMessage(event.getMessageEditor().getMessage(MessageEditor.MessageType.WARNING,
+ "commands.music.queue.error.title",
+ "commands.music.queue.error.description"
+ ).build()).queue();
+ } else {
+ Set queue = new AudioManager().getTrackManager(event.getGuild()).getQueuedTracks();
+ EmbedBuilder b = event.getMessageEditor().getMessage(MessageEditor.MessageType.INFO,
+ "commands.music.queue.success.title",
+ "commands.music.queue.success.description")
+ .addField("Queued songs", String.valueOf(queue.size()), true);
+ for (AudioInfo g : queue) {
+ b.addField(g.getTrack().getInfo().author, g.getTrack().getInfo().title, true);
+ }
+ event.getTextChannel().sendMessage(b.build()).queue();
+ }
+ }
+
+ @Override
+ public String[] labels() {
+ return new String[]{"queue"};
+ }
+
+ @Override
+ public String description() {
+ return "Shows the music queue.";
+ }
+
+ @Override
+ public String usage() {
+ return "";
+ }
+}
diff --git a/src/main/java/com/bbn/hadder/commands/music/StopCommand.java b/src/main/java/com/bbn/hadder/commands/music/StopCommand.java
new file mode 100644
index 0000000..ab03799
--- /dev/null
+++ b/src/main/java/com/bbn/hadder/commands/music/StopCommand.java
@@ -0,0 +1,39 @@
+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
+ */
+
+public class StopCommand implements Command {
+
+ @Override
+ public void executed(String[] args, CommandEvent event) {
+ new AudioManager().players.remove(event.getGuild().getId());
+ new AudioManager().getPlayer(event.getGuild()).destroy();
+ new 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
+ public String[] labels() {
+ return new String[]{"stop"};
+ }
+
+ @Override
+ public String description() {
+ return "commands.music.stop.help.description";
+ }
+
+ @Override
+ public String usage() {
+ return "";
+ }
+}
diff --git a/src/main/java/com/bbn/hadder/utils/AudioPlayerSendHandler.java b/src/main/java/com/bbn/hadder/utils/AudioPlayerSendHandler.java
deleted file mode 100644
index ff3f483..0000000
--- a/src/main/java/com/bbn/hadder/utils/AudioPlayerSendHandler.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.bbn.hadder.utils;
-
-/*
- * @author Skidder / GregTCLTK
- */
-
-import net.dv8tion.jda.api.audio.AudioSendHandler;
-
-import javax.annotation.Nullable;
-import java.nio.ByteBuffer;
-
-public class AudioPlayerSendHandler implements AudioSendHandler {
-
- @Override
- public boolean canProvide() {
- return false;
- }
-
- @Nullable
- @Override
- public ByteBuffer provide20MsAudio() {
-
- return null;
- }
-}
diff --git a/src/main/java/com/bbn/hadder/utils/MessageEditor.java b/src/main/java/com/bbn/hadder/utils/MessageEditor.java
index 2f22d85..c7205f1 100644
--- a/src/main/java/com/bbn/hadder/utils/MessageEditor.java
+++ b/src/main/java/com/bbn/hadder/utils/MessageEditor.java
@@ -56,7 +56,7 @@ public class MessageEditor {
switch (type) {
case INFO:
builder
- .setColor(new Color(47, 94, 105))
+ .setColor(new Color(78, 156, 174))
.setFooter("Hadder", "https://bigbotnetwork.com/images/Hadder.png")
.setTimestamp(Instant.now());
break;