diff --git a/.gitignore b/.gitignore
index 10c9d5b..f94094e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.idea/
**/target/
**/data/
-**/settings.json
\ No newline at end of file
+**/settings.json
+**/logs/
\ No newline at end of file
diff --git a/Makefile b/Makefile
index ddaa989..f017364 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,13 @@
SHELL := /bin/bash
build:
- docker-compose build
+ docker rmi siren && docker-compose build
test:
docker run --rm -it siren:latest bash
up:
+ if [[ "$(docker images -q siren 2> /dev/null)" == "" ]]; then docker-compose build; fi; \
docker-compose up -d
down:
@@ -15,3 +16,5 @@ down:
exec:
docker exec -it siren bash
+clean:
+ docker rmi siren
diff --git a/docker-compose.yml b/docker-compose.yml
index 3356e83..62a6462 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -9,7 +9,7 @@ services:
dockerfile: ./Dockerfile
args:
- JAVA_VERSION=17
- - VERSION=0.1.8
+ - VERSION=0.1.9
volumes:
- ./data:/app
restart: unless-stopped
diff --git a/pom.xml b/pom.xml
index f1604b9..faae4f4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.bensherriff
siren
- 0.1.8
+ 0.1.9
jar
@@ -26,6 +26,11 @@
m2-dv8tion
https://m2.dv8tion.net/releases
+
+ maven_central
+ Maven Central
+ https://repo.maven.apache.org/maven2/
+
@@ -47,17 +52,17 @@
central
ffc58a58b429-releases
- http://repo.local.bensherriff.com/artifactory/libs-release
+ https://repo.local.bensherriff.com/artifactory/libs-release
- 5.0.0-beta.3
- 1.3.77
+ 5.0.0-beta.6
+ 1.3.78
1.3.13
- 2.14.0
+ 2.14.2
2.0.6
- 2.19.0
+ 2.20.0
UTF-8
17
17
@@ -92,16 +97,6 @@
-
- org.slf4j
- slf4j-api
- ${slf4j.version}
-
-
- org.slf4j
- slf4j-simple
- ${slf4j.version}
-
org.apache.logging.log4j
log4j-api
@@ -112,6 +107,11 @@
log4j-core
${log4j.version}
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ ${log4j.version}
+
diff --git a/src/main/java/com/bensherriff/siren/MusicBot.java b/src/main/java/com/bensherriff/siren/MusicBot.java
index 5ae549f..a28e164 100644
--- a/src/main/java/com/bensherriff/siren/MusicBot.java
+++ b/src/main/java/com/bensherriff/siren/MusicBot.java
@@ -1,20 +1,16 @@
package com.bensherriff.siren;
-import com.bensherriff.siren.listener.Listener;
-import com.bensherriff.siren.listener.SlashListener;
-import com.bensherriff.siren.listener.TextListener;
+import com.bensherriff.siren.audio.Listener;
import com.bensherriff.siren.settings.Settings;
import com.bensherriff.siren.settings.SettingsManager;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
-import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.util.Arrays;
@@ -41,8 +37,7 @@ public class MusicBot {
private static void start() throws IOException {
Settings settings = SettingsManager.load();
-// Listener textListener = new TextListener(settings);
- Listener slashListener = new SlashListener(settings);
+ Listener listener = new Listener(settings);
if (settings.getToken() == null || settings.getToken().isEmpty()) {
throw new IOException("Token field may not be empty, please set the value in " + SettingsManager.PATH);
@@ -54,12 +49,9 @@ public class MusicBot {
.enableCache(Arrays.asList(ENABLED_FLAGS))
.disableCache(Arrays.asList(DISABLED_FLAGS))
.setActivity(Activity.playing("nothing"))
- .setStatus(OnlineStatus.INVISIBLE)
-// .addEventListeners(textListener)
- .addEventListeners(slashListener)
+ .addEventListeners(listener)
.setBulkDeleteSplittingEnabled(true)
.build();
-// textListener.setJDA(jda);
- slashListener.setJDA(jda);
+ listener.setJDA(jda);
}
}
diff --git a/src/main/java/com/bensherriff/siren/audio/AudioHandler.java b/src/main/java/com/bensherriff/siren/audio/AudioHandler.java
index c82934c..99438e6 100644
--- a/src/main/java/com/bensherriff/siren/audio/AudioHandler.java
+++ b/src/main/java/com/bensherriff/siren/audio/AudioHandler.java
@@ -38,17 +38,25 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
}
public void addTrack(AudioTrack track) {
- if (player.getPlayingTrack() == null) {
- player.playTrack(track);
- } else {
- queue.add(track);
+ if (!player.startTrack(track, true)) {
+ if (!queue.offer(track)) {
+ LOGGER.error("Failed to queue track {}", track.getInfo().title);
+ }
}
}
+ public void nextTrack() {
+ player.startTrack(queue.poll(), false);
+ }
+
public void setPaused(boolean paused) {
player.setPaused(paused);
}
+ public boolean isPaused() {
+ return player.isPaused();
+ }
+
public void stopTrack() {
player.stopTrack();
}
@@ -69,16 +77,19 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
@Override
public void onTrackStart(AudioPlayer player, AudioTrack track) {
+ manager.getListener().getJDA().getPresence().setActivity(Activity.listening(track.getInfo().title));
super.onTrackStart(player, track);
}
@Override
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
-// LOGGER.debug("Track ended: " + endReason.name() + "; starting next: " + endReason.mayStartNext);
- if (queue.isEmpty()) {
- manager.getListener().closeAudioConnection(guildID);
+ LOGGER.debug("Track ended due to {}; {} ", endReason.name(), endReason.mayStartNext ? "starting next track" : "closing connection");
+ if (endReason.mayStartNext) {
+ nextTrack();
} else {
- player.playTrack(queue.poll());
+ queue.clear();
+ manager.getListener().closeAudioConnection(guildID);
+ manager.getListener().getJDA().getPresence().setActivity(Activity.playing("nothing"));
}
}
diff --git a/src/main/java/com/bensherriff/siren/listener/Listener.java b/src/main/java/com/bensherriff/siren/audio/Listener.java
similarity index 60%
rename from src/main/java/com/bensherriff/siren/listener/Listener.java
rename to src/main/java/com/bensherriff/siren/audio/Listener.java
index 77cf67a..872566a 100644
--- a/src/main/java/com/bensherriff/siren/listener/Listener.java
+++ b/src/main/java/com/bensherriff/siren/audio/Listener.java
@@ -1,17 +1,15 @@
-package com.bensherriff.siren.listener;
+package com.bensherriff.siren.audio;
-import com.bensherriff.siren.audio.AudioHandler;
-import com.bensherriff.siren.audio.PlayerManager;
-import com.bensherriff.siren.commands.Command;
+import com.bensherriff.siren.commands.*;
import com.bensherriff.siren.exceptions.EmptyVoiceChannelException;
import com.bensherriff.siren.settings.GuildSettings;
import com.bensherriff.siren.settings.Settings;
import com.bensherriff.siren.settings.SettingsManager;
-import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.session.ReadyEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.managers.AudioManager;
@@ -20,17 +18,19 @@ import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
-public abstract class Listener extends ListenerAdapter {
- protected static final Logger LOGGER = LogManager.getLogger(Listener.class);
+public class Listener extends ListenerAdapter {
+ private static final Logger LOGGER = LogManager.getLogger(Listener.class);
- protected final PlayerManager playerManager;
- protected final Map musicManagers;
- protected final Settings settings;
- protected JDA jda;
-
- Map commands = new HashMap<>();
+ private final PlayerManager playerManager;
+ private final Map musicManagers;
+ private final Settings settings;
+ private final Map commands = new HashMap<>();
+ private JDA jda;
public Listener(Settings settings) {
this.musicManagers = new HashMap<>();
@@ -38,6 +38,29 @@ public abstract class Listener extends ListenerAdapter {
this.playerManager = new PlayerManager(this);
this.playerManager.initialize();
+
+ commands.put("play", new PlayCommand(this));
+ commands.put("stop", new StopCommand(this));
+ commands.put("skip", new SkipCommand(this));
+ commands.put("volume", new VolumeCommand(this));
+ commands.put("pause", new PauseCommand(this));
+ commands.put("resume", new ResumeCommand(this));
+ }
+
+ public PlayerManager getPlayerManager() {
+ return playerManager;
+ }
+
+ public Map getMusicManagers() {
+ return musicManagers;
+ }
+
+ public Settings getSettings() {
+ return settings;
+ }
+
+ public Map getCommands() {
+ return commands;
}
public JDA getJDA() {
@@ -48,14 +71,6 @@ public abstract class Listener extends ListenerAdapter {
this.jda = jda;
}
- public Settings getSettings() {
- return settings;
- }
-
- public PlayerManager getPlayerManager() {
- return playerManager;
- }
-
public void closeAudioConnection(long guildID) {
Guild guild = jda.getGuildById(guildID);
if (guild != null) {
@@ -63,6 +78,21 @@ public abstract class Listener extends ListenerAdapter {
}
}
+ public void connectToVoiceChannel(String userID, AudioManager audioManager) throws EmptyVoiceChannelException {
+ if (!audioManager.isConnected()) {
+ Member member = audioManager.getGuild().getMemberById(userID);
+ if (member != null) {
+ if (member.getVoiceState() != null && member.getVoiceState().inAudioChannel()) {
+ VoiceChannel voiceChannel = Objects.requireNonNull(member.getVoiceState().getChannel()).asVoiceChannel();
+ LOGGER.debug("Connecting to channel {} in guild {}", voiceChannel.getId(), voiceChannel.getGuild().getId());
+ audioManager.openAudioConnection(voiceChannel);
+ } else {
+ throw new EmptyVoiceChannelException("Member {} is not connected to a voice channel");
+ }
+ }
+ }
+ }
+
public synchronized AudioHandler getGuildAudioPlayer(Guild guild) throws IOException {
long guildId = Long.parseLong(guild.getId());
AudioHandler audioHandler = musicManagers.get(guildId);
@@ -87,53 +117,29 @@ public abstract class Listener extends ListenerAdapter {
@Override
public void onReady(@NotNull ReadyEvent event) {
super.onReady(event);
+ jda.getGuilds().forEach(guild -> {
+ LOGGER.debug("Updating commands for {}", guild.getId());
+ guild.updateCommands().addCommands(commands.values().stream().map(Command::getSlashCommandData).collect(Collectors.toList())).queue();
+ });
+ super.onReady(event);
+ LOGGER.info("Ready!");
}
- public void playTrack(Guild guild, String userID, AudioHandler audioHandler, AudioTrack track) throws EmptyVoiceChannelException {
- connectToVoiceChannel(userID, guild.getAudioManager());
- audioHandler.addTrack(track);
- }
+ @Override
+ public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
+ String command = event.getName();
+ event.deferReply().queue();
- public void stopTrack(Guild guild) throws IOException {
- AudioHandler audioHandler = getGuildAudioPlayer(guild);
- audioHandler.stopTrack();
- guild.getAudioManager().closeAudioConnection();
- }
-
- public void skipTrack(Guild guild) throws IOException {
- AudioHandler audioHandler = getGuildAudioPlayer(guild);
- audioHandler.stopTrack();
- }
-
- public void pauseTrack(Guild guild) throws IOException {
- AudioHandler audioHandler = getGuildAudioPlayer(guild);
- audioHandler.setPaused(true);
- }
-
- public void resumeTrack(Guild guild) throws IOException {
- AudioHandler audioHandler = getGuildAudioPlayer(guild);
- audioHandler.setPaused(false);
- }
-
- public void changeVolume(Guild guild, int volume) throws IOException {
- AudioHandler audioHandler = getGuildAudioPlayer(guild);
- settings.getGuildSettings().get(guild.getIdLong()).setVolume(volume);
- SettingsManager.write(getSettings());
- audioHandler.setVolume(volume);
- }
-
- public void connectToVoiceChannel(String userID, AudioManager audioManager) throws EmptyVoiceChannelException {
- if (!audioManager.isConnected()) {
- Member member = audioManager.getGuild().getMemberById(userID);
- if (member != null) {
- if (member.getVoiceState() != null && member.getVoiceState().inAudioChannel()) {
- VoiceChannel voiceChannel = Objects.requireNonNull(member.getVoiceState().getChannel()).asVoiceChannel();
- LOGGER.debug("Connecting to channel {} in guild {}", voiceChannel.getId(), voiceChannel.getGuild().getId());
- audioManager.openAudioConnection(voiceChannel);
- } else {
- throw new EmptyVoiceChannelException("Member {} is not connected to a voice channel");
- }
+ try {
+ if (commands.containsKey(command)) {
+ commands.get(command).doCommand(event);
+ } else {
+ event.getHook().sendMessage("Unexpected command received.").queue();
}
+ } catch (Exception ex) {
+ LOGGER.error(ex.getMessage());
+ event.getHook().sendMessage("An error occurred while processing your command. Please contact your administrator.").queue();
}
+ super.onSlashCommandInteraction(event);
}
}
diff --git a/src/main/java/com/bensherriff/siren/audio/PlayerManager.java b/src/main/java/com/bensherriff/siren/audio/PlayerManager.java
index c4b26d8..7561d7f 100644
--- a/src/main/java/com/bensherriff/siren/audio/PlayerManager.java
+++ b/src/main/java/com/bensherriff/siren/audio/PlayerManager.java
@@ -1,6 +1,5 @@
package com.bensherriff.siren.audio;
-import com.bensherriff.siren.listener.Listener;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
diff --git a/src/main/java/com/bensherriff/siren/commands/Command.java b/src/main/java/com/bensherriff/siren/commands/Command.java
index 18b0078..dff016d 100644
--- a/src/main/java/com/bensherriff/siren/commands/Command.java
+++ b/src/main/java/com/bensherriff/siren/commands/Command.java
@@ -1,18 +1,40 @@
package com.bensherriff.siren.commands;
-import com.bensherriff.siren.listener.Listener;
+import com.bensherriff.siren.audio.Listener;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.IOException;
public abstract class Command {
+ protected static final Logger LOGGER = LogManager.getLogger(Command.class);
+
+
protected final Listener listener;
- protected String name;
+ protected SlashCommandData slashCommandData;
+
+ protected boolean required = false;
public Command(Listener listener) {
this.listener = listener;
}
- public abstract void doCommand(CommandEvent event);
+ public abstract void doCommand(SlashCommandInteractionEvent event) throws IOException;
- public String getName() {
- return name;
+ public SlashCommandData getSlashCommandData() {
+ return slashCommandData;
+ }
+
+ protected Guild getGuild(SlashCommandInteractionEvent event) throws IOException {
+ Guild guild = event.getGuild();
+ if (guild == null) {
+ throw new IOException("Could not find the current guild.");
+ }
+ else {
+ return guild;
+ }
}
}
diff --git a/src/main/java/com/bensherriff/siren/commands/CommandEvent.java b/src/main/java/com/bensherriff/siren/commands/CommandEvent.java
deleted file mode 100644
index edbbf1b..0000000
--- a/src/main/java/com/bensherriff/siren/commands/CommandEvent.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.bensherriff.siren.commands;
-
-import com.bensherriff.siren.audio.AudioHandler;
-import com.bensherriff.siren.exceptions.InvalidCommandException;
-import com.bensherriff.siren.listener.Listener;
-import net.dv8tion.jda.api.entities.Guild;
-import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class CommandEvent {
-
- private final Command command;
- private final String userId;
- private final Guild guild;
- private final List args = new ArrayList<>();
- private final AudioHandler audioHandler;
- private final TextChannel textChannel;
-
- private CommandEvent(CommandBuilder builder) {
- this.command = builder.command;
- this.userId = builder.userId;
- this.guild = builder.guild;
- this.args.addAll(builder.args);
- this.audioHandler = builder.audioHandler;
- this.textChannel = builder.textChannel;
- }
-
- public Command getCommand() {
- return command;
- }
-
- public String getUserId() {
- return userId;
- }
-
- public Guild getGuild() {
- return guild;
- }
-
- public List getArgs() {
- return args;
- }
-
- public AudioHandler getAudioHandler() {
- return audioHandler;
- }
-
- public TextChannel getTextChannel() {
- return textChannel;
- }
-
- public static class CommandBuilder {
- private final Listener listener;
- private final String commandText;
- private final String userId;
- private Command command;
- private Guild guild;
- private List args = new ArrayList<>();
- private AudioHandler audioHandler;
- private TextChannel textChannel;
-
- public CommandBuilder(Listener listener, String commandText, String userId) {
- this.listener = listener;
- this.commandText = commandText;
- this.userId = userId;
- }
-
- public CommandBuilder setGuild(Guild guild) {
- this.guild = guild;
- return this;
- }
-
- public CommandBuilder setArgs(List args) {
- this.args = args;
- return this;
- }
-
- public CommandBuilder setAudioHandler(AudioHandler audioHandler) {
- this.audioHandler = audioHandler;
- return this;
- }
-
- public CommandBuilder setTextChannel(TextChannel textChannel) {
- this.textChannel = textChannel;
- return this;
- }
-
- public CommandEvent build() throws InvalidCommandException {
- if ("play".equals(this.commandText)) {
- this.command = new PlayCommand(this.listener);
- } else {
- throw new InvalidCommandException(this.commandText + " is not a valid command");
- }
- return new CommandEvent(this);
- }
- }
-}
diff --git a/src/main/java/com/bensherriff/siren/commands/PauseCommand.java b/src/main/java/com/bensherriff/siren/commands/PauseCommand.java
new file mode 100644
index 0000000..c257303
--- /dev/null
+++ b/src/main/java/com/bensherriff/siren/commands/PauseCommand.java
@@ -0,0 +1,29 @@
+package com.bensherriff.siren.commands;
+
+import com.bensherriff.siren.audio.AudioHandler;
+import com.bensherriff.siren.audio.Listener;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
+
+import java.io.IOException;
+
+public class PauseCommand extends Command {
+
+ public PauseCommand(Listener listener) {
+ super(listener);
+ slashCommandData = Commands.slash("pause", "Pause the current track");
+ }
+
+ @Override
+ public void doCommand(SlashCommandInteractionEvent event) throws IOException {
+ Guild guild = getGuild(event);
+ AudioHandler audioHandler = listener.getGuildAudioPlayer(guild);
+ if (audioHandler.isPaused()) {
+ event.getHook().sendMessage("Playback is already paused.").queue();
+ } else {
+ audioHandler.setPaused(false);
+ event.getHook().sendMessage("Pausing track...").queue();
+ }
+ }
+}
diff --git a/src/main/java/com/bensherriff/siren/commands/PlayCommand.java b/src/main/java/com/bensherriff/siren/commands/PlayCommand.java
index 2168011..ac73366 100644
--- a/src/main/java/com/bensherriff/siren/commands/PlayCommand.java
+++ b/src/main/java/com/bensherriff/siren/commands/PlayCommand.java
@@ -2,38 +2,42 @@ package com.bensherriff.siren.commands;
import com.bensherriff.siren.audio.AudioHandler;
import com.bensherriff.siren.exceptions.EmptyVoiceChannelException;
-import com.bensherriff.siren.listener.Listener;
+import com.bensherriff.siren.audio.Listener;
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.channel.concrete.TextChannel;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
import java.io.IOException;
+import java.util.Objects;
public class PlayCommand extends Command {
public PlayCommand(Listener listener) {
super(listener);
- this.name = "play";
+ slashCommandData = Commands.slash("play", "Play a track from a URL")
+ .addOption(OptionType.STRING, "url", "Track URL", true);
}
@Override
- public void doCommand(CommandEvent event) {
+ public void doCommand(SlashCommandInteractionEvent event) throws IOException {
+ String userID = event.getUser().getId();
+ Guild guild = getGuild(event);
+ String trackURL = Objects.requireNonNull(event.getOption("url")).getAsString();
+ AudioHandler audioHandler = listener.getGuildAudioPlayer(guild);
- }
-
- private void loadAndPlay(final TextChannel channel, final String userID, final String trackUrl) throws IOException {
- AudioHandler audioHandler = this.listener.getGuildAudioPlayer(channel.getGuild());
- Listener listener = this.listener;
- listener.getPlayerManager().loadItemOrdered(audioHandler, trackUrl, new AudioLoadResultHandler() {
+ listener.getPlayerManager().loadItemOrdered(audioHandler, trackURL, new AudioLoadResultHandler() {
@Override
public void trackLoaded(AudioTrack track) {
try {
- listener.playTrack(channel.getGuild(), userID, audioHandler, track);
- channel.sendMessage("Adding **" + track.getInfo().title + "** to queue").queue();
+ playTrack(guild, userID, audioHandler, track);
+ event.getHook().sendMessage("Adding **" + track.getInfo().title + "** to queue...").queue();
} catch (EmptyVoiceChannelException e) {
- channel.sendMessage("You must connect to a voice channel first!").queue();
+ event.getHook().sendMessage("You must be connected to a voice channel in order to play tracks!").queue();
}
}
@@ -46,22 +50,33 @@ public class PlayCommand extends Command {
}
try {
- listener.playTrack(channel.getGuild(), userID, audioHandler, firstTrack);
- channel.sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")").queue();
+ playTrack(guild, userID, audioHandler, firstTrack);
+ event.getHook().sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")...").queue();
} catch (EmptyVoiceChannelException e) {
- channel.sendMessage("You must connect to a voice channel first!").queue();
+ event.getHook().sendMessage("You must be connected to a voice channel in order to play tracks!").queue();
}
}
@Override
public void noMatches() {
- channel.sendMessage("Nothing found by " + trackUrl).queue();
+ event.getHook().sendMessage("Nothing found by " + trackURL).queue();
}
@Override
public void loadFailed(FriendlyException exception) {
- channel.sendMessage("Could not play: " + exception.getMessage()).queue();
+ String msg = "Failed to play track";
+ if (exception.getMessage().contains("Unknown file format")) {
+ event.getHook().sendMessage(msg + ". " + exception.getMessage()).queue();
+ } else {
+ event.getHook().sendMessage(msg + ". Please contact your administrator.").queue();
+ }
+ LOGGER.error("{}: {}", msg, exception.getMessage());
}
});
}
+
+ public void playTrack(Guild guild, String userID, AudioHandler audioHandler, AudioTrack track) throws EmptyVoiceChannelException {
+ listener.connectToVoiceChannel(userID, guild.getAudioManager());
+ audioHandler.addTrack(track);
+ }
}
diff --git a/src/main/java/com/bensherriff/siren/commands/ResumeCommand.java b/src/main/java/com/bensherriff/siren/commands/ResumeCommand.java
new file mode 100644
index 0000000..ac4f871
--- /dev/null
+++ b/src/main/java/com/bensherriff/siren/commands/ResumeCommand.java
@@ -0,0 +1,29 @@
+package com.bensherriff.siren.commands;
+
+import com.bensherriff.siren.audio.AudioHandler;
+import com.bensherriff.siren.audio.Listener;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
+
+import java.io.IOException;
+
+public class ResumeCommand extends Command {
+
+ public ResumeCommand(Listener listener) {
+ super(listener);
+ slashCommandData = Commands.slash("resume", "Resume the current track");
+ }
+
+ @Override
+ public void doCommand(SlashCommandInteractionEvent event) throws IOException {
+ Guild guild = getGuild(event);
+ AudioHandler audioHandler = listener.getGuildAudioPlayer(guild);
+ if (audioHandler.isPaused()) {
+ audioHandler.setPaused(false);
+ event.getHook().sendMessage("Resuming track...").queue();
+ } else {
+ event.getHook().sendMessage("Playback is not currently paused.").queue();
+ }
+ }
+}
diff --git a/src/main/java/com/bensherriff/siren/commands/SkipCommand.java b/src/main/java/com/bensherriff/siren/commands/SkipCommand.java
new file mode 100644
index 0000000..cee7044
--- /dev/null
+++ b/src/main/java/com/bensherriff/siren/commands/SkipCommand.java
@@ -0,0 +1,25 @@
+package com.bensherriff.siren.commands;
+
+import com.bensherriff.siren.audio.AudioHandler;
+import com.bensherriff.siren.audio.Listener;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
+
+import java.io.IOException;
+
+public class SkipCommand extends Command {
+
+ public SkipCommand(Listener listener) {
+ super(listener);
+ slashCommandData = Commands.slash("skip", "Skip the current track");
+ }
+
+ @Override
+ public void doCommand(SlashCommandInteractionEvent event) throws IOException {
+ Guild guild = getGuild(event);
+ AudioHandler audioHandler = listener.getGuildAudioPlayer(guild);
+ audioHandler.nextTrack();
+ event.getHook().sendMessage("Skipping track...").queue();
+ }
+}
diff --git a/src/main/java/com/bensherriff/siren/commands/StopCommand.java b/src/main/java/com/bensherriff/siren/commands/StopCommand.java
new file mode 100644
index 0000000..38dfbb5
--- /dev/null
+++ b/src/main/java/com/bensherriff/siren/commands/StopCommand.java
@@ -0,0 +1,26 @@
+package com.bensherriff.siren.commands;
+
+import com.bensherriff.siren.audio.AudioHandler;
+import com.bensherriff.siren.audio.Listener;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
+
+import java.io.IOException;
+
+public class StopCommand extends Command {
+
+ public StopCommand(Listener listener) {
+ super(listener);
+ slashCommandData = Commands.slash("stop", "Stop playing tracks and clear the queue");
+ }
+
+ @Override
+ public void doCommand(SlashCommandInteractionEvent event) throws IOException {
+ Guild guild = getGuild(event);
+ AudioHandler audioHandler = listener.getGuildAudioPlayer(guild);
+ audioHandler.stopTrack();
+ guild.getAudioManager().closeAudioConnection();
+ event.getHook().sendMessage("Stopping the current track and clearing the queue...").queue();
+ }
+}
diff --git a/src/main/java/com/bensherriff/siren/commands/VolumeCommand.java b/src/main/java/com/bensherriff/siren/commands/VolumeCommand.java
new file mode 100644
index 0000000..8dbe3b7
--- /dev/null
+++ b/src/main/java/com/bensherriff/siren/commands/VolumeCommand.java
@@ -0,0 +1,32 @@
+package com.bensherriff.siren.commands;
+
+import com.bensherriff.siren.audio.AudioHandler;
+import com.bensherriff.siren.audio.Listener;
+import com.bensherriff.siren.settings.SettingsManager;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
+
+import java.io.IOException;
+import java.util.Objects;
+
+public class VolumeCommand extends Command {
+
+ public VolumeCommand(Listener listener) {
+ super(listener);
+ slashCommandData = Commands.slash("volume", "Set the volume")
+ .addOption(OptionType.INTEGER, "volume", "Updated value", true);
+ }
+
+ @Override
+ public void doCommand(SlashCommandInteractionEvent event) throws IOException {
+ Guild guild = getGuild(event);
+ int volume = Objects.requireNonNull(event.getOption("volume")).getAsInt();
+ listener.getSettings().getGuildSettings().get(guild.getIdLong()).setVolume(volume);
+ SettingsManager.write(listener.getSettings());
+ AudioHandler audioHandler = listener.getGuildAudioPlayer(guild);
+ audioHandler.setVolume(volume);
+ event.getHook().sendMessage("Setting volume to " + volume + "...").queue();
+ }
+}
diff --git a/src/main/java/com/bensherriff/siren/listener/SlashListener.java b/src/main/java/com/bensherriff/siren/listener/SlashListener.java
deleted file mode 100644
index c5ccfb9..0000000
--- a/src/main/java/com/bensherriff/siren/listener/SlashListener.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package com.bensherriff.siren.listener;
-
-import com.bensherriff.siren.audio.AudioHandler;
-import com.bensherriff.siren.exceptions.EmptyVoiceChannelException;
-import com.bensherriff.siren.settings.Settings;
-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.Guild;
-import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
-import net.dv8tion.jda.api.events.session.ReadyEvent;
-import net.dv8tion.jda.api.interactions.commands.OptionType;
-import net.dv8tion.jda.api.interactions.commands.build.Commands;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.IOException;
-import java.util.Objects;
-
-public class SlashListener extends Listener {
-
- public SlashListener(Settings settings) {
- super(settings);
- }
-
- @Override
- public void onReady(@NotNull ReadyEvent event) {
- jda.getGuilds().forEach(guild -> {
- guild.updateCommands().addCommands(
- Commands.slash("play", "Play a track from a URL")
- .addOption(OptionType.STRING, "url", "Track URL", true),
- Commands.slash("skip", "Skip the current track"),
- Commands.slash("stop", "Stop playing tracks and clear the queue"),
- Commands.slash("volume", "Set the volume")
- .addOption(OptionType.INTEGER, "volume", "Updated Volume", true),
- Commands.slash("pause", "Pause the current track"),
- Commands.slash("resume", "Resume the current paused track")
- ).queue();
- });
- super.onReady(event);
- }
-
- @Override
- public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
-
- String userId = event.getUser().getId();
- Guild guild = event.getGuild();
- String command = event.getName();
- event.deferReply().queue();
-
- try {
- switch (command) {
- case "play" -> {
- String trackURL = Objects.requireNonNull(event.getOption("url")).getAsString();
- loadAndPlay(guild, userId, trackURL, event);
- }
- case "skip" -> {
- skipTrack(guild);
- event.getHook().sendMessage("Skipped to the next track").queue();
- }
- case "stop" -> {
- stopTrack(guild);
- event.getHook().sendMessage("Stopped track and cleared queue").queue();
- }
- case "volume" -> {
- int volume = Objects.requireNonNull(event.getOption("volume")).getAsInt();
- try {
- changeVolume(guild, volume);
- } catch (IOException ex) {
- event.getHook().sendMessage("Unable to set the volume").queue();
- LOGGER.error(ex.getMessage());
- }
- event.getHook().sendMessage("Set volume to " + volume).queue();
- }
- case "pause" -> {
- pauseTrack(guild);
- event.getHook().sendMessage("Pausing track").queue();
- }
- case "resume" -> {
- resumeTrack(guild);
- event.getHook().sendMessage("Resumed track").queue();
- }
- default -> event.getHook().sendMessage("Invalid command").queue();
- }
- } catch (IOException ex) {
- LOGGER.error(ex.getMessage());
- }
- super.onSlashCommandInteraction(event);
- }
-
- private void loadAndPlay(Guild guild, final String userID, final String trackUrl, SlashCommandInteractionEvent event) throws IOException {
- AudioHandler audioHandler = getGuildAudioPlayer(guild);
-
- playerManager.loadItemOrdered(audioHandler, trackUrl, new AudioLoadResultHandler() {
- @Override
- public void trackLoaded(AudioTrack track) {
- try {
- playTrack(guild, userID, audioHandler, track);
- event.getHook().sendMessage("Adding **" + track.getInfo().title + "** to queue").queue();
- } catch (EmptyVoiceChannelException e) {
- event.getHook().sendMessage("You must connect to a voice channel first!").queue();
- }
- }
-
- @Override
- public void playlistLoaded(AudioPlaylist playlist) {
- AudioTrack firstTrack = playlist.getSelectedTrack();
-
- if (firstTrack == null) {
- firstTrack = playlist.getTracks().get(0);
- }
-
- try {
- playTrack(guild, userID, audioHandler, firstTrack);
- event.getHook().sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")").queue();
- } catch (EmptyVoiceChannelException e) {
- event.getHook().sendMessage("You must connect to a voice channel first!").queue();
- }
- }
-
- @Override
- public void noMatches() {
- event.getHook().sendMessage("Nothing found by " + trackUrl).queue();
- }
-
- @Override
- public void loadFailed(FriendlyException exception) {
- event.getHook().sendMessage("Could not play: " + exception.getMessage()).queue();
- }
- });
- }
-}
diff --git a/src/main/java/com/bensherriff/siren/listener/TextListener.java b/src/main/java/com/bensherriff/siren/listener/TextListener.java
deleted file mode 100644
index 32f673f..0000000
--- a/src/main/java/com/bensherriff/siren/listener/TextListener.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package com.bensherriff.siren.listener;
-
-import com.bensherriff.siren.audio.AudioHandler;
-import com.bensherriff.siren.commands.CommandEvent;
-import com.bensherriff.siren.exceptions.EmptyVoiceChannelException;
-import com.bensherriff.siren.exceptions.InvalidCommandException;
-import com.bensherriff.siren.settings.Settings;
-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.Guild;
-import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
-import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-public class TextListener extends Listener {
-
- public TextListener(Settings settings) {
- super(settings);
- }
-
- @Override
- public void onMessageReceived(@NotNull MessageReceivedEvent event) {
- if (event.getAuthor().isBot()) return;
-
-// Command command = parseCommand(event.getMessage().getContentRaw().split(" "));
- String[] command = event.getMessage().getContentRaw().split(" ");
- TextChannel channel = event.getChannel().asTextChannel();
- String userID = event.getAuthor().getId();
- Guild guild = channel.getGuild();
-
- try {
- if ("!play".equals(command[0]) && command.length == 2) {
- loadAndPlay(channel, userID, command[1]);
- } else if ("!skip".equals(command[0])) {
- skipTrack(guild);
- channel.sendMessage("Skipped to the next track").queue();
- } else if ("!stop".equals(command[0])) {
- stopTrack(guild);
- channel.sendMessage("Stopped track and cleared queue").queue();
- } else if ("!volume".equals(command[0]) && command.length == 2) {
- int volume = Integer.parseInt(command[1]);
- try {
- changeVolume(guild, volume);
- } catch (IOException ex) {
- channel.sendMessage("Unable to update the settings file.").queue();
- LOGGER.error(ex.getMessage());
- }
- channel.sendMessage("Set volume to " + command[1]).queue();
- } else if ("!pause".equals(command[0])) {
- pauseTrack(guild);
- channel.sendMessage("Paused track").queue();
- } else if ("!resume".equals(command[0])) {
- resumeTrack(guild);
- channel.sendMessage("Resumed track").queue();
- }
- } catch (IOException ex) {
- LOGGER.error(ex.getMessage());
- }
-
- super.onMessageReceived(event);
- }
-
- private CommandEvent parseCommand(MessageReceivedEvent event) throws IOException, InvalidCommandException {
- String[] input = event.getMessage().getContentRaw().split(" ");
- TextChannel channel = event.getChannel().asTextChannel();
- String userID = event.getAuthor().getId();
- Guild guild = channel.getGuild();
- AudioHandler audioHandler = getGuildAudioPlayer(guild);
-
- return new CommandEvent.CommandBuilder(this, input[0], userID)
- .setTextChannel(channel)
- .setGuild(guild)
- .setAudioHandler(audioHandler)
- .setArgs(Arrays.asList(input).subList(1, input.length))
- .build();
- }
-
- private void loadAndPlay(final TextChannel channel, final String userID, final String trackUrl) throws IOException {
- AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild());
-
- playerManager.loadItemOrdered(audioHandler, trackUrl, new AudioLoadResultHandler() {
- @Override
- public void trackLoaded(AudioTrack track) {
- try {
- playTrack(channel.getGuild(), userID, audioHandler, track);
- channel.sendMessage("Adding **" + track.getInfo().title + "** to queue").queue();
- } catch (EmptyVoiceChannelException e) {
- channel.sendMessage("You must connect to a voice channel first!").queue();
- }
- }
-
- @Override
- public void playlistLoaded(AudioPlaylist playlist) {
- AudioTrack firstTrack = playlist.getSelectedTrack();
-
- if (firstTrack == null) {
- firstTrack = playlist.getTracks().get(0);
- }
-
- try {
- playTrack(channel.getGuild(), userID, audioHandler, firstTrack);
- channel.sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")").queue();
- } catch (EmptyVoiceChannelException e) {
- channel.sendMessage("You must connect to a voice channel first!").queue();
- }
- }
-
- @Override
- public void noMatches() {
- channel.sendMessage("Nothing found by " + trackUrl).queue();
- }
-
- @Override
- public void loadFailed(FriendlyException exception) {
- channel.sendMessage("Could not play: " + exception.getMessage()).queue();
- }
- });
- }
-}
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
index 447b8eb..32c93a1 100644
--- a/src/main/resources/log4j2.xml
+++ b/src/main/resources/log4j2.xml
@@ -1,13 +1,33 @@
+
+ logs
+ siren
+ %d{HH:mm:ss.SSS} | %-5level | %msg%n
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
\ No newline at end of file