From 2e3e44ad58dd732b1565e84dedd2d68181b694e5 Mon Sep 17 00:00:00 2001 From: Benjamin Sherriff Date: Mon, 23 Jan 2023 17:17:33 -0500 Subject: [PATCH] v0.1.4 - Built out slash commands --- README.md | 13 +++ pom.xml | 2 +- .../java/com/bensherriff/siren/MusicBot.java | 4 +- .../siren/listener/CommandEvent.java | 13 +++ .../bensherriff/siren/listener/Listener.java | 62 +++--------- .../siren/listener/SlashListener.java | 99 +++++++++++++++++++ .../siren/listener/TextListener.java | 59 +++++++++-- 7 files changed, 193 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 356f316..2e127a0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,19 @@ # Siren A Java/Docker Discord music bot +## Running +Visit the [Discord Developer Portal](https://discord.com/developers/applications) and create a new application. +Guides and more information are available [here](https://discord.com/developers/docs/intro). + +### OAuth2 URL Generator +The bot requires the following permissions/scopes: +- bot +- applications.commands + +``` +https://discord.com/api/oauth2/authorize?client_id=&permissions=1088840792896&scope=applications.commands%20bot +``` + `docker build -t siren .` `docker-compose up -d` diff --git a/pom.xml b/pom.xml index dc0b22f..4dcc473 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.bensherriff siren - 0.1.3 + 0.1.4 jar diff --git a/src/main/java/com/bensherriff/siren/MusicBot.java b/src/main/java/com/bensherriff/siren/MusicBot.java index c7d6494..38983df 100644 --- a/src/main/java/com/bensherriff/siren/MusicBot.java +++ b/src/main/java/com/bensherriff/siren/MusicBot.java @@ -1,6 +1,7 @@ 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.settings.Settings; import com.bensherriff.siren.settings.SettingsManager; @@ -38,7 +39,8 @@ public class MusicBot { private static void start() throws IOException, LoginException { SettingsManager settingsManager = new SettingsManager(); Settings settings = settingsManager.load(); - listener = new TextListener(settings); +// listener = new TextListener(settings); + listener = new SlashListener(settings); JDA jda = JDABuilder.create(settings.getToken(), Arrays.asList(INTENTS)) .enableCache(Arrays.asList(ENABLED_FLAGS)) diff --git a/src/main/java/com/bensherriff/siren/listener/CommandEvent.java b/src/main/java/com/bensherriff/siren/listener/CommandEvent.java index 438ed05..1c58639 100644 --- a/src/main/java/com/bensherriff/siren/listener/CommandEvent.java +++ b/src/main/java/com/bensherriff/siren/listener/CommandEvent.java @@ -1,6 +1,7 @@ package com.bensherriff.siren.listener; import com.bensherriff.siren.audio.AudioHandler; +import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import java.util.ArrayList; @@ -10,6 +11,7 @@ public class CommandEvent { private final String command; private final String userId; + private final Guild guild; private final List args = new ArrayList<>(); private final AudioHandler audioHandler; private final TextChannel textChannel; @@ -17,6 +19,7 @@ public class CommandEvent { 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; @@ -30,6 +33,10 @@ public class CommandEvent { return userId; } + public Guild getGuild() { + return guild; + } + public List getArgs() { return args; } @@ -45,6 +52,7 @@ public class CommandEvent { public static class CommandBuilder { private final String command; private final String userId; + private Guild guild; private List args = new ArrayList<>(); private AudioHandler audioHandler; private TextChannel textChannel; @@ -54,6 +62,11 @@ public class CommandEvent { this.userId = userId; } + public CommandBuilder setGuild(Guild guild) { + this.guild = guild; + return this; + } + public CommandBuilder setArgs(List args) { this.args = args; return this; diff --git a/src/main/java/com/bensherriff/siren/listener/Listener.java b/src/main/java/com/bensherriff/siren/listener/Listener.java index 9e93052..63f6981 100644 --- a/src/main/java/com/bensherriff/siren/listener/Listener.java +++ b/src/main/java/com/bensherriff/siren/listener/Listener.java @@ -80,76 +80,36 @@ public abstract class Listener extends ListenerAdapter { super.onReady(event); } - protected void loadAndPlay(final TextChannel channel, final String userID, final String trackUrl) { - AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); - - playerManager.loadItemOrdered(audioHandler, trackUrl, new AudioLoadResultHandler() { - @Override - public void trackLoaded(AudioTrack track) { - channel.sendMessage("Adding **" + track.getInfo().title + "** to queue").queue(); - playTrack(channel.getGuild(), userID, audioHandler, track); - } - - @Override - public void playlistLoaded(AudioPlaylist playlist) { - AudioTrack firstTrack = playlist.getSelectedTrack(); - - if (firstTrack == null) { - firstTrack = playlist.getTracks().get(0); - } - - channel.sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")").queue(); - playTrack(channel.getGuild(), userID, audioHandler, firstTrack); - } - - @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(); - } - }); - } - protected void playTrack(Guild guild, String userID, AudioHandler audioHandler, AudioTrack track) { connectToVoiceChannel(userID, guild.getAudioManager()); audioHandler.addTrack(track); } - protected void stopTrack(TextChannel channel) { - AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + protected void stopTrack(Guild guild) { + AudioHandler audioHandler = getGuildAudioPlayer(guild); audioHandler.stopTrack(); - channel.getGuild().getAudioManager().closeAudioConnection(); - channel.sendMessage("Stopping music").queue(); + guild.getAudioManager().closeAudioConnection(); } - protected void skipTrack(TextChannel channel) { - AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + protected void skipTrack(Guild guild) { + AudioHandler audioHandler = getGuildAudioPlayer(guild); audioHandler.stopTrack(); - channel.sendMessage("Skipped to next track").queue(); } - protected void pauseTrack(TextChannel channel) { - AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + protected void pauseTrack(Guild guild) { + AudioHandler audioHandler = getGuildAudioPlayer(guild); audioHandler.setPaused(true); - channel.sendMessage("Paused track").queue(); } - protected void resumeTrack(TextChannel channel) { - AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + protected void resumeTrack(Guild guild) { + AudioHandler audioHandler = getGuildAudioPlayer(guild); audioHandler.setPaused(false); - channel.sendMessage("Resumed track").queue(); } - protected void changeVolume(TextChannel channel, String vol) { - AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); - int volume = Integer.parseInt(vol); + protected void changeVolume(Guild guild, int volume) { + AudioHandler audioHandler = getGuildAudioPlayer(guild); getSettings().setVolume(volume); audioHandler.setVolume(volume); - channel.sendMessage("Set volume to " + volume).queue(); } private void connectToVoiceChannel(String userID, AudioManager audioManager) { diff --git a/src/main/java/com/bensherriff/siren/listener/SlashListener.java b/src/main/java/com/bensherriff/siren/listener/SlashListener.java index 33ca801..11fcac0 100644 --- a/src/main/java/com/bensherriff/siren/listener/SlashListener.java +++ b/src/main/java/com/bensherriff/siren/listener/SlashListener.java @@ -1,17 +1,116 @@ package com.bensherriff.siren.listener; +import com.bensherriff.siren.audio.AudioHandler; 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.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.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(); + + 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(); + changeVolume(guild, volume); + 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(); + } + } super.onSlashCommandInteraction(event); } + + private void loadAndPlay(Guild guild, final String userID, final String trackUrl, SlashCommandInteractionEvent event) { + AudioHandler audioHandler = getGuildAudioPlayer(guild); + + playerManager.loadItemOrdered(audioHandler, trackUrl, new AudioLoadResultHandler() { + @Override + public void trackLoaded(AudioTrack track) { + event.getHook().sendMessage("Adding **" + track.getInfo().title + "** to queue").queue(); + playTrack(guild, userID, audioHandler, track); + } + + @Override + public void playlistLoaded(AudioPlaylist playlist) { + AudioTrack firstTrack = playlist.getSelectedTrack(); + + if (firstTrack == null) { + firstTrack = playlist.getTracks().get(0); + } + + event.getHook().sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")").queue(); + playTrack(guild, userID, audioHandler, firstTrack); + } + + @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 index 25b2e29..92e2077 100644 --- a/src/main/java/com/bensherriff/siren/listener/TextListener.java +++ b/src/main/java/com/bensherriff/siren/listener/TextListener.java @@ -2,6 +2,11 @@ package com.bensherriff.siren.listener; import com.bensherriff.siren.audio.AudioHandler; 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; @@ -21,10 +26,12 @@ public class TextListener extends Listener { String[] command = event.getMessage().getContentRaw().split(" "); TextChannel channel = event.getChannel().asTextChannel(); String userID = event.getAuthor().getId(); - AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + Guild guild = channel.getGuild(); + AudioHandler audioHandler = getGuildAudioPlayer(guild); CommandEvent commandEvent = new CommandEvent.CommandBuilder(command[0], userID) .setTextChannel(channel) + .setGuild(guild) .setAudioHandler(audioHandler) .setArgs(Arrays.asList(command).subList(1, command.length)) .build(); @@ -32,17 +39,57 @@ public class TextListener extends Listener { if ("!play".equals(command[0]) && command.length == 2) { loadAndPlay(channel, userID, command[1]); } else if ("!skip".equals(command[0])) { - skipTrack(channel); + skipTrack(guild); + channel.sendMessage("Skipped to the next track").queue(); } else if ("!stop".equals(command[0])) { - stopTrack(channel); + stopTrack(guild); + channel.sendMessage("Stopped track and cleared queue").queue(); } else if ("!volume".equals(command[0]) && command.length == 2) { - changeVolume(channel, command[1]); + int volume = Integer.parseInt(command[1]); + changeVolume(guild, volume); + channel.sendMessage("Set volume to " + command[1]).queue(); } else if ("!pause".equals(command[0])) { - pauseTrack(channel); + pauseTrack(guild); + channel.sendMessage("Paused track").queue(); } else if ("!resume".equals(command[0])) { - resumeTrack(channel); + resumeTrack(guild); + channel.sendMessage("Resumed track").queue(); } super.onMessageReceived(event); } + + private void loadAndPlay(final TextChannel channel, final String userID, final String trackUrl) { + AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + + playerManager.loadItemOrdered(audioHandler, trackUrl, new AudioLoadResultHandler() { + @Override + public void trackLoaded(AudioTrack track) { + channel.sendMessage("Adding **" + track.getInfo().title + "** to queue").queue(); + playTrack(channel.getGuild(), userID, audioHandler, track); + } + + @Override + public void playlistLoaded(AudioPlaylist playlist) { + AudioTrack firstTrack = playlist.getSelectedTrack(); + + if (firstTrack == null) { + firstTrack = playlist.getTracks().get(0); + } + + channel.sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")").queue(); + playTrack(channel.getGuild(), userID, audioHandler, firstTrack); + } + + @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(); + } + }); + } }