v0.1.9 Cleanup and organization

This commit is contained in:
2023-03-27 21:41:37 -04:00
parent 1a2e9bbb98
commit 14952bf791
19 changed files with 342 additions and 487 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
**/target/
**/data/
**/settings.json
**/logs/

View File

@@ -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

View File

@@ -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

32
pom.xml
View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.bensherriff</groupId>
<artifactId>siren</artifactId>
<version>0.1.8</version>
<version>0.1.9</version>
<packaging>jar</packaging>
<repositories>
@@ -26,6 +26,11 @@
<name>m2-dv8tion</name>
<url>https://m2.dv8tion.net/releases</url>
</repository>
<repository>
<id>maven_central</id>
<name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
@@ -47,17 +52,17 @@
<repository>
<id>central</id>
<name>ffc58a58b429-releases</name>
<url>http://repo.local.bensherriff.com/artifactory/libs-release</url>
<url>https://repo.local.bensherriff.com/artifactory/libs-release</url>
</repository>
</distributionManagement>
<properties>
<jda.version>5.0.0-beta.3</jda.version>
<lavaplayer.version>1.3.77</lavaplayer.version>
<jda.version>5.0.0-beta.6</jda.version>
<lavaplayer.version>1.3.78</lavaplayer.version>
<lavaplayer-natives-extra.version>1.3.13</lavaplayer-natives-extra.version>
<jackson.version>2.14.0</jackson.version>
<jackson.version>2.14.2</jackson.version>
<slf4j.version>2.0.6</slf4j.version>
<log4j.version>2.19.0</log4j.version>
<log4j.version>2.20.0</log4j.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
@@ -92,16 +97,6 @@
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
@@ -112,6 +107,11 @@
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
<build>

View File

@@ -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);
}
}

View File

@@ -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"));
}
}

View File

@@ -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<Long, AudioHandler> musicManagers;
protected final Settings settings;
protected JDA jda;
Map<String, Command> commands = new HashMap<>();
private final PlayerManager playerManager;
private final Map<Long, AudioHandler> musicManagers;
private final Settings settings;
private final Map<String, Command> 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<Long, AudioHandler> getMusicManagers() {
return musicManagers;
}
public Settings getSettings() {
return settings;
}
public Map<String, Command> 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);
try {
if (commands.containsKey(command)) {
commands.get(command).doCommand(event);
} else {
throw new EmptyVoiceChannelException("Member {} is not connected to a voice channel");
}
}
}
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);
}
}

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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<String> 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<String> 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<String> 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<String> 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);
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
});
}
}

View File

@@ -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();
}
});
}
}

View File

@@ -1,13 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="logPath">logs</Property>
<Property name="rollingFileName">siren</Property>
<Property name="LOG_PATTERN">%d{HH:mm:ss.SSS} | %-5level | %msg%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} | %-5level | %msg%n"/>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
<RollingFile name="rollingFile" fileName="${logPath}/${rollingFileName}-debug.log"
filePattern="${logPath}/${rollingFileName}-%d{yyyy-MM-dd}-%i.log">
<LevelRangeFilter minLevel="DEBUG" maxLevel="FATAL" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{DEFAULT} | %-5level | %c{1}.%M() | %msg%n%throwable{short.lineNumber}"/>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="50 MB" />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
<Logger name="com.bensherriff" additivity="false">
<AppenderRef ref="console"/>
<AppenderRef ref="rollingFile"/>
</Logger>
<Root level="all" additivity="false">
<AppenderRef ref="rollingFile"/>
</Root>
</Loggers>
</Configuration>