diff --git a/Dockerfile b/Dockerfile index cc852a0..b855b52 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM eclipse-temurin:17-jdk-alpine as build +FROM eclipse-temurin:17-jdk-alpine AS build COPY .mvn/ .mvn COPY mvnw pom.xml ./ diff --git a/pom.xml b/pom.xml index ae14c69..a50d518 100644 --- a/pom.xml +++ b/pom.xml @@ -101,17 +101,17 @@ net.dv8tion JDA - 5.1.0 + 5.1.2 dev.arbjerg lavaplayer - 2.2.1 + 2.2.2 dev.lavalink.youtube v2 - 1.7.2 + 1.8.3 diff --git a/src/main/java/me/bobert/netneutrality/command/music/BitconnectCommand.java b/src/main/java/me/bobert/netneutrality/command/music/BitconnectCommand.java index 2315e56..f9202de 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/BitconnectCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/BitconnectCommand.java @@ -52,10 +52,10 @@ public class BitconnectCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(SlashCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); + MusicManager manager = MusicManager.get(context.getGuild()); context.ephemeral(); - player.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, true); + manager.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, true); return CommandExecutionResult.success("Ready to invest?"); } } diff --git a/src/main/java/me/bobert/netneutrality/command/music/ClearQueueCommand.java b/src/main/java/me/bobert/netneutrality/command/music/ClearQueueCommand.java index a6cd04e..90f0950 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/ClearQueueCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/ClearQueueCommand.java @@ -7,11 +7,9 @@ package me.bobert.netneutrality.command.music; */ import me.bobert.netneutrality.command.AbstractMusicCommand; -import me.bobert.netneutrality.context.MessageCommandContext; import me.bobert.netneutrality.context.SlashCommandContext; import me.bobert.netneutrality.core.command.CommandExecutionResult; import me.bobert.netneutrality.music.MusicManager; -import me.bobert.netneutrality.utils.MessageFunction; import me.bobert.netneutrality.utils.MusicUtils; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; @@ -43,57 +41,15 @@ public class ClearQueueCommand extends AbstractMusicCommand { } @Override - public CommandExecutionResult execute(MessageCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); + public CommandExecutionResult execute(SlashCommandContext context) { + MusicManager manager = MusicManager.get(context.getGuild()); + context.ack(); - if (!MusicUtils.checkIfConnected(context)) - return CommandExecutionResult.none(); - - if (context.getArgs().length == 0) { - context.reply("Select the track you want to delete from the queue (track# or all)"); - context.reply(MessageFunction.buildViewQueueMessage(player, true)); - } - - if (context.getArgs().length > 0) { - - int queueSize = player.getQueueSize(); - if (context.getArgument(0).equals("all")) { - - if (queueSize > 0) { - player.getScheduler().getQueueManager().clearQueue(); - context.reply(String.format("Removed %d track%s from the queue", queueSize--, (queueSize > 1 ? "s" : ""))); - } else { - context.reply("Queue is empty!"); - } - } else { - - try { - int num = Integer.parseInt(context.getArgument(0)); - - if (num > 0) { - return player.getScheduler().getQueueManager().removeFromQueue(num); - } else { - context.reply("Number out of range"); - } - - } catch (NumberFormatException e) { - context.reply("Please enter a number"); - } - } + if (MusicUtils.checkIfConnected(context)) { + return manager.getQueueManager().clearQueue(); } return CommandExecutionResult.none(); } - @Override - public CommandExecutionResult execute(SlashCommandContext context) { - MusicManager manager = MusicManager.get(context.getGuild()); - context.ack(); - - if (!MusicUtils.checkIfConnected(context)) - return CommandExecutionResult.none(); - - return manager.getScheduler().getQueueManager().clearQueue(); - } - } diff --git a/src/main/java/me/bobert/netneutrality/command/music/JoinCommand.java b/src/main/java/me/bobert/netneutrality/command/music/JoinCommand.java index 8006e89..6096b14 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/JoinCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/JoinCommand.java @@ -37,10 +37,8 @@ public class JoinCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - if (MusicUtils.checkIfNotConnected(context)) { + if (MusicUtils.connect(context)) { context.reply("Joining current voice channel"); - - MusicUtils.connect(context, true); } return CommandExecutionResult.none(); @@ -48,10 +46,8 @@ public class JoinCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(SlashCommandContext context) { - if (MusicUtils.checkIfNotConnected(context)) { + if (MusicUtils.connect(context)) { context.reply("Joining current voice channel"); - - MusicUtils.connect(context, true); } return CommandExecutionResult.none(); diff --git a/src/main/java/me/bobert/netneutrality/command/music/LeaveCommand.java b/src/main/java/me/bobert/netneutrality/command/music/LeaveCommand.java index ccaa16b..311cb10 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/LeaveCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/LeaveCommand.java @@ -38,11 +38,11 @@ public class LeaveCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); + MusicManager manager = MusicManager.get(context.getGuild()); if (MusicUtils.checkIfConnected(context)) { context.reply("Leaving voice channel and clearing queue"); - player.leave(); + manager.disconnect(); } return CommandExecutionResult.none(); @@ -50,11 +50,11 @@ public class LeaveCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(SlashCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); + MusicManager manager = MusicManager.get(context.getGuild()); if (MusicUtils.checkIfConnected(context)) { context.reply("Leaving voice channel and clearing queue"); - player.leave(); + manager.disconnect(); } return CommandExecutionResult.none(); diff --git a/src/main/java/me/bobert/netneutrality/command/music/QueueCommand.java b/src/main/java/me/bobert/netneutrality/command/music/QueueCommand.java index 7e6a097..370d44a 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/QueueCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/QueueCommand.java @@ -6,10 +6,10 @@ package me.bobert.netneutrality.command.music; */ import me.bobert.netneutrality.command.AbstractMusicCommand; -import me.bobert.netneutrality.context.MessageCommandContext; import me.bobert.netneutrality.context.SlashCommandContext; import me.bobert.netneutrality.core.command.CommandExecutionResult; import me.bobert.netneutrality.music.MusicManager; +import me.bobert.netneutrality.music.QueueManager; import me.bobert.netneutrality.utils.MessageFunction; import me.bobert.netneutrality.utils.MusicUtils; import net.dv8tion.jda.api.entities.Member; @@ -59,77 +59,35 @@ public class QueueCommand extends AbstractMusicCommand { ); } - @Override - public CommandExecutionResult execute(MessageCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); - - if (!MusicUtils.checkIfConnected(context)) - return CommandExecutionResult.none(); - - if (context.getArgs().length == 0) { - context.reply("Select the track you want to delete from the queue (track# or all)"); - context.reply(MessageFunction.buildViewQueueMessage(player, true)); - } - - if (context.getArgs().length > 0) { - - int queueSize = player.getQueueSize(); - if (context.getArgument(0).equals("all")) { - - if (queueSize > 0) { - player.getScheduler().getQueueManager().clearQueue(); - context.reply(String.format("Removed %d track%s from the queue", queueSize--, (queueSize > 1 ? "s" : ""))); - } else { - context.reply("Queue is empty!"); - } - } else { - - try { - int num = Integer.parseInt(context.getArgument(0)); - - if (num > 0) { - return player.getScheduler().getQueueManager().removeFromQueue(num); - } else { - context.reply("Number out of range"); - } - - } catch (NumberFormatException e) { - context.reply("Please enter a number"); - } - } - } - - return CommandExecutionResult.none(); - } - @Override public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); + QueueManager queueManager = manager.getQueueManager(); context.ack(); - String sub = context.getEvent().getFullCommandName().split(" ")[1]; + String sub = context.getSubCommand(); if (MusicUtils.checkIfConnected(context)) { switch (sub) { case "clear-all" -> { - return manager.getScheduler().getQueueManager().clearQueue(); + return queueManager.clearQueue(); } case "delete-track" -> { int position = context.getEvent().getOption("position", 0, OptionMapping::getAsInt); - return manager.getScheduler().getQueueManager().removeFromQueue(position); + return queueManager.removeFromQueue(position); } case "show-queue" -> { - if (manager.getQueueSize() == 0) { + if (queueManager.getQueueSize() == 0) { return CommandExecutionResult.info("Queue is empty!"); } - context.reply(MessageFunction.buildViewQueueMessage(manager, true)); + context.reply(MessageFunction.buildViewQueueMessage(manager)); } case "shuffle" -> { - return manager.getScheduler().getQueueManager().shuffle(); + return queueManager.shuffle(); } case "from-user" -> { @@ -147,16 +105,12 @@ public class QueueCommand extends AbstractMusicCommand { return CommandExecutionResult.warn("The user isn't from this guild"); } - int size = manager.getScheduler() - .getQueueManager() - .getQueueWithFilter(trackInfo -> member.equals(trackInfo.getRequester())) - .size(); - + int size = queueManager.getQueueWithFilter(trackInfo -> member.equals(trackInfo.getRequester())).size(); if (size == 0) { return CommandExecutionResult.info(String.format("No tracks added by user %s", member.getEffectiveName())); } - manager.getScheduler().getQueueManager().removeTracksFromUser(member); + queueManager.removeTracksFromUser(member); context.reply("Removed all tracks from user %s", member.getEffectiveName()); } } diff --git a/src/main/java/me/bobert/netneutrality/command/music/ResumeCommand.java b/src/main/java/me/bobert/netneutrality/command/music/ResumeCommand.java new file mode 100644 index 0000000..971f8ce --- /dev/null +++ b/src/main/java/me/bobert/netneutrality/command/music/ResumeCommand.java @@ -0,0 +1,45 @@ +package me.bobert.netneutrality.command.music;/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +import me.bobert.netneutrality.command.AbstractMusicCommand; +import me.bobert.netneutrality.context.SlashCommandContext; +import me.bobert.netneutrality.core.command.CommandExecutionResult; +import me.bobert.netneutrality.music.MusicManager; +import me.bobert.netneutrality.utils.MusicUtils; +import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; + +public class ResumeCommand extends AbstractMusicCommand { + @Override + public boolean isEnabled() { + return true; + } + + @Override + public String getCommandName() { + return "resume"; + } + + @Override + public String getDescription() { + return "Resume the music player at the next track if it was stopped using the command /stop"; + } + + @Override + public void registerSlashCommandOptions(SlashCommandData data) { + + } + + @Override + public CommandExecutionResult execute(SlashCommandContext context) { + MusicManager manager = MusicManager.get(context.getGuild()); + + if (MusicUtils.checkIfConnected(context)) { + return manager.getQueueManager().skip(); + } + + return CommandExecutionResult.none(); + } +} diff --git a/src/main/java/me/bobert/netneutrality/command/music/ShuffleCommand.java b/src/main/java/me/bobert/netneutrality/command/music/ShuffleCommand.java index fbc08a3..69c75dd 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/ShuffleCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/ShuffleCommand.java @@ -40,7 +40,7 @@ public class ShuffleCommand extends AbstractMusicCommand { context.ack(); if (MusicUtils.checkIfConnected(context)) { - return manager.getScheduler().getQueueManager().shuffle(); + return manager.getQueueManager().shuffle(); } return CommandExecutionResult.none(); diff --git a/src/main/java/me/bobert/netneutrality/command/music/SkipCommand.java b/src/main/java/me/bobert/netneutrality/command/music/SkipCommand.java index 9a927c6..2aa901f 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/SkipCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/SkipCommand.java @@ -43,27 +43,25 @@ public class SkipCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); + MusicManager manager = MusicManager.get(context.getGuild()); - if (!MusicUtils.checkIfConnected(context)) + if (!MusicUtils.checkIfConnected(context)) { return CommandExecutionResult.none(); + } if (UserFunction.isAdmin(context.getGuildUser()) || MusicUtils.isUserDj(context.getGuildUser())) { if (UserFunction.isAdmin(context.getGuildUser()) && context.getArgs().length > 0) { try { int skips = Integer.parseInt(context.getArgument(0)); - player.getScheduler().getQueueManager().skip(skips); - - context.reply("Skipping %s track%s", skips, (skips > 1 ? "s" : "")); + return manager.getQueueManager().skip(skips); } catch (NumberFormatException e) { context.reply("Please enter how many track(s) to skip"); } } else { - player.getScheduler().getQueueManager().skip(1); - context.reply("Skipping current track"); + return manager.getQueueManager().skip(1); } } else { - player.voteSkip(context); + return manager.voteSkip(context); } return CommandExecutionResult.none(); @@ -72,11 +70,11 @@ public class SkipCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(SlashCommandContext context) { MusicManager manager = MusicManager.get(context.getGuild()); - int skips = context.getEvent().getOption("skip", 1, OptionMapping::getAsInt); context.ack(); if (MusicUtils.checkIfConnected(context)) { - return manager.getScheduler().getQueueManager().skip(skips); + int skips = context.getEvent().getOption("skip", 1, OptionMapping::getAsInt); + return manager.getQueueManager().skip(skips); } return CommandExecutionResult.none(); diff --git a/src/main/java/me/bobert/netneutrality/command/music/StopCommand.java b/src/main/java/me/bobert/netneutrality/command/music/StopCommand.java index 70b9182..3d67d43 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/StopCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/StopCommand.java @@ -39,15 +39,14 @@ public class StopCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); + MusicManager manager = MusicManager.get(context.getGuild()); - if (!MusicUtils.checkIfConnected(context)) - return CommandExecutionResult.none(); - - // Need a resume command before - if (UserFunction.isAdmin(context.getGuildUser())) { - player.stopTrack(); - context.reply("Stopping current track"); + if (MusicUtils.checkIfConnected(context)) { + // Need a resume command before + if (UserFunction.isAdmin(context.getGuildUser())) { + manager.stopTrack(); + context.reply("Stopping current track"); + } } return CommandExecutionResult.none(); diff --git a/src/main/java/me/bobert/netneutrality/command/music/ViewQueueCommand.java b/src/main/java/me/bobert/netneutrality/command/music/ViewQueueCommand.java index ec8031a..edb1d19 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/ViewQueueCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/ViewQueueCommand.java @@ -38,12 +38,12 @@ public class ViewQueueCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); + MusicManager manager = MusicManager.get(context.getGuild()); if (MusicUtils.checkIfConnected(context)) { - int queueSize = player.getQueueSize(); + int queueSize = manager.getQueueSize(); if (queueSize > 0) { - context.reply(MessageFunction.buildViewQueueMessage(player, true)); + context.reply(MessageFunction.buildViewQueueMessage(manager)); } else { context.reply("Queue is empty!"); } @@ -63,7 +63,7 @@ public class ViewQueueCommand extends AbstractMusicCommand { return CommandExecutionResult.warn("Queue is empty!"); } - context.reply(MessageFunction.buildViewQueueMessage(manager, true)); + context.reply(MessageFunction.buildViewQueueMessage(manager)); } return CommandExecutionResult.none(); diff --git a/src/main/java/me/bobert/netneutrality/command/music/VolumeCommand.java b/src/main/java/me/bobert/netneutrality/command/music/VolumeCommand.java index d5906c6..9d7fef2 100644 --- a/src/main/java/me/bobert/netneutrality/command/music/VolumeCommand.java +++ b/src/main/java/me/bobert/netneutrality/command/music/VolumeCommand.java @@ -43,7 +43,7 @@ public class VolumeCommand extends AbstractMusicCommand { @Override public CommandExecutionResult execute(MessageCommandContext context) { - MusicManager player = MusicManager.get(context.getGuild()); + MusicManager manager = MusicManager.get(context.getGuild()); if (!MusicUtils.checkIfConnected(context)) return CommandExecutionResult.none(); @@ -53,7 +53,7 @@ public class VolumeCommand extends AbstractMusicCommand { int volume = Integer.parseInt(context.getArgument(0)); if (volume > 0 && volume <= 100) { - player.setVolume(volume); + manager.setVolume(volume); context.reply("Volume set to %s", volume); } else throw new NumberFormatException(); diff --git a/src/main/java/me/bobert/netneutrality/context/MusicChannelContext.java b/src/main/java/me/bobert/netneutrality/context/MusicChannelContext.java index e805b5b..aa8094e 100644 --- a/src/main/java/me/bobert/netneutrality/context/MusicChannelContext.java +++ b/src/main/java/me/bobert/netneutrality/context/MusicChannelContext.java @@ -7,6 +7,7 @@ package me.bobert.netneutrality.context; import me.bobert.netneutrality.core.AsyncMessage; import me.bobert.netneutrality.core.context.AbstractContext; +import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; import net.dv8tion.jda.api.events.Event; import net.dv8tion.jda.api.interactions.InteractionHook; @@ -18,8 +19,8 @@ import java.util.function.Consumer; public class MusicChannelContext extends AbstractContext { - public MusicChannelContext(GuildMessageChannel channel) { - super(channel.getJDA(), channel.getGuild(), channel, null, null); + public MusicChannelContext(GuildMessageChannel channel, Member member) { + super(channel.getJDA(), channel.getGuild(), channel, member, member.getUser()); } @Override diff --git a/src/main/java/me/bobert/netneutrality/music/MusicManager.java b/src/main/java/me/bobert/netneutrality/music/MusicManager.java index a6e1961..ae7957c 100644 --- a/src/main/java/me/bobert/netneutrality/music/MusicManager.java +++ b/src/main/java/me/bobert/netneutrality/music/MusicManager.java @@ -23,7 +23,6 @@ import me.bobert.netneutrality.thread.MusicPlayerAutoDisconnectThread; import me.bobert.netneutrality.utils.MusicUtils; import me.bobert.netneutrality.utils.Settings; import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -78,6 +77,29 @@ public class MusicManager { dev.lavalink.youtube.clients.Web.setPoTokenAndVisitorData(po, visitor); } + public static void disconnectPlayers() { + for (MusicManager mm : managers.values()) { + mm.getQueueManager().clearQueue(); + mm.player.destroy(); + } + } + + public TrackScheduler getScheduler() { + return scheduler; + } + + public QueueManager getQueueManager() { + return scheduler.getQueueManager(); + } + + public AudioPlayer getPlayer() { + return player; + } + + public Guild getGuild() { + return guild; + } + public boolean isNotConnectedTo(AudioChannel vChannel) { return vChannel == null || !vChannel.equals(guild.getAudioManager().getConnectedChannel()); } @@ -96,6 +118,21 @@ public class MusicManager { } } + public synchronized void disconnect() { + if (guild != null && guild.getAudioManager().getConnectedChannel() != null) { + logger.debug("Guild {}: disconnecting from voice channel {}", guild.getId(), guild.getAudioManager().getConnectedChannel().getId()); + player.stopTrack(); + guild.getAudioManager().closeAudioConnection(); + } + + scheduler.detachContext(); + + if (autoDisconnectThread != null) { + autoDisconnectThread.cancel(true); + autoDisconnectThread = null; + } + } + public boolean isConnected() { return guild != null && guild.getAudioManager().getConnectedChannel() != null; } @@ -108,45 +145,6 @@ public class MusicManager { return player.getPlayingTrack() != null; } - public synchronized Member getRequesterOfCurrentTrack() { - QueueManager.TrackInfo info = scheduler.getQueueManager().peekHeadOfQueue(); - - if (info == null) - return null; - - return info.getRequester(); - } - - protected AudioPlayer getPlayer() { - return player; - } - - public Guild getGuild() { - return guild; - } - - public synchronized void leave() { - if (guild != null && guild.getAudioManager().getConnectedChannel() != null) { - logger.debug("Guild {}: leaving voice channel {}", guild.getId(), guild.getAudioManager().getConnectedChannel().getId()); - player.stopTrack(); - guild.getAudioManager().closeAudioConnection(); - } - - scheduler.detachTextChannel(); - - if (autoDisconnectThread != null) { - autoDisconnectThread.cancel(true); - autoDisconnectThread = null; - } - } - - public static void disconnectPlayers() { - for (MusicManager mm : managers.values()) { - mm.getScheduler().getQueueManager().clearQueue(); - mm.player.destroy(); - } - } - public synchronized void play(String query, CommandContext context) { play(query, context, false); } @@ -173,7 +171,6 @@ public class MusicManager { public synchronized CommandExecutionResult voteSkip(CommandContext context) { AudioChannel audioChannel = guild.getAudioManager().getConnectedChannel(); - if (audioChannel == null) { return CommandExecutionResult.warn("Bot is not connected to a voice channel"); } @@ -182,7 +179,7 @@ public class MusicManager { return CommandExecutionResult.warn("No tracks are currently playing"); } - QueueManager.TrackInfo info = scheduler.getQueueManager().peekHeadOfQueue(); + TrackInfo info = getQueueManager().peekHeadOfQueue(); if (info == null) { return CommandExecutionResult.warn("Queue is empty"); } @@ -191,7 +188,7 @@ public class MusicManager { int connected = audioChannel.getMembers().size() - 1; if (connected < 3) { - scheduler.getQueueManager().skip(); + getQueueManager().skip(); return CommandExecutionResult.info("Skipping current track since not enough people are connected to the voice channel."); } @@ -202,7 +199,7 @@ public class MusicManager { logger.debug("VoteSkip: guild={}, connected={}, needed={}, skips={}, user={}", context.getGuild().getId(), connected, needed, info.getSkips().size(), context.getGuildUser().getId()); if (info.getSkips().size() > needed) { - return scheduler.getQueueManager().skip(); + return getQueueManager().skip(); } return CommandExecutionResult.success(String.format("Adding your vote to skip the current track. Current votes: %d/%d", @@ -216,10 +213,6 @@ public class MusicManager { } public int getQueueSize() { - return scheduler.getQueueManager().getQueueSize(); - } - - public TrackScheduler getScheduler() { - return scheduler; + return getQueueManager().getQueueSize(); } } diff --git a/src/main/java/me/bobert/netneutrality/music/QueueManager.java b/src/main/java/me/bobert/netneutrality/music/QueueManager.java index c81207d..aa20163 100644 --- a/src/main/java/me/bobert/netneutrality/music/QueueManager.java +++ b/src/main/java/me/bobert/netneutrality/music/QueueManager.java @@ -18,68 +18,7 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.function.Predicate; public class QueueManager { - - public static class TrackInfo { - - private final AudioTrack track; - private final Member member; - private final Set skips; - private static final Logger logger = LogManager.getLogger(QueueManager.class); - - public TrackInfo(AudioTrack track, Member member) { - this.track = track; - this.member = member; - this.skips = new HashSet<>(); - } - - public AudioTrack getTrack() { - return track; - } - - public Set getSkips() { - return skips; - } - - public void addSkip(Member member) { - if (!hasSkip(member)) { - logger.debug("VoteSkip: user={}, skip doesn't exist, before={}, after={}", member.getId(), skips.size(), skips.size() + 1); - skips.add(member.getId()); - } - } - - public boolean hasSkip(Member member) { - return skips.contains(member.getId()); - } - - public Member getRequester() { - return member; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TrackInfo trackInfo = (TrackInfo) o; - return track.equals(trackInfo.track); - } - - @Override - public int hashCode() { - return Objects.hash(track); - } - - @Override - public String toString() { - return "TrackInfo{" + - "track=" + track.getInfo().title + - ", member=" + member.getEffectiveName() + - ", skips=" + skips + - '}'; - } - } - private final Logger logger = LogManager.getLogger(QueueManager.class); - private final TrackScheduler scheduler; private final AudioPlayer player; private final Guild guild; @@ -99,10 +38,6 @@ public class QueueManager { } } - public TrackScheduler getScheduler() { - return scheduler; - } - public Guild getGuild() { return guild; } @@ -138,7 +73,7 @@ public class QueueManager { } public CommandExecutionResult clearQueue() { - scheduler.getMusicManager().leave(); + scheduler.getMusicManager().disconnect(); if (queue.isEmpty()) { return CommandExecutionResult.warn("Queue is empty!"); @@ -175,7 +110,7 @@ public class QueueManager { } } - public ArrayList getAllQueuedTrack() { + public List getAllQueuedTracks() { synchronized (queue) { ArrayList tracks = new ArrayList<>(); @@ -228,13 +163,18 @@ public class QueueManager { } public CommandExecutionResult skip(int nbTrack) { - if (nbTrack == 0) { + if (nbTrack < 1) { nbTrack = 1; } + if (queue.isEmpty()) { + scheduler.getMusicManager().disconnect(); + return CommandExecutionResult.info("Queue is empty, leaving voice channel"); + } + synchronized (queue) { if (queue.isEmpty()) { - scheduler.getMusicManager().leave(); + scheduler.getMusicManager().disconnect(); return CommandExecutionResult.info("Queue is empty, leaving voice channel"); } @@ -248,7 +188,7 @@ public class QueueManager { } if (queue.isEmpty()) { - scheduler.getMusicManager().leave(); + scheduler.getMusicManager().disconnect(); return CommandExecutionResult.info("Queue is empty, leaving voice channel"); } @@ -259,27 +199,27 @@ public class QueueManager { } public CommandExecutionResult shuffle() { - if (queue.size() > 3) { - return CommandExecutionResult.none(); + if (queue.size() <= 3) { + return CommandExecutionResult.warn("The queue is too small to be shuffled"); } synchronized (queue) { - if (queue.size() > 3) { - logger.debug("Guild {}: shuffling queue", guild.getId()); - TrackInfo current = queue.poll(); - - ArrayList newQueue = new ArrayList<>(queue); - - Collections.shuffle(newQueue); - - queue.clear(); - queue.add(current); - queue.addAll(newQueue); - - return CommandExecutionResult.success("Queue is now shuffled."); + if (queue.size() <= 3) { + return CommandExecutionResult.warn("The queue is too small to be shuffled"); } - return CommandExecutionResult.none(); + logger.debug("Guild {}: shuffling queue", guild.getId()); + TrackInfo current = queue.poll(); + + ArrayList newQueue = new ArrayList<>(queue); + + Collections.shuffle(newQueue); + + queue.clear(); + queue.add(current); + queue.addAll(newQueue); + + return CommandExecutionResult.success("The queue is now shuffled."); } } diff --git a/src/main/java/me/bobert/netneutrality/music/TrackInfo.java b/src/main/java/me/bobert/netneutrality/music/TrackInfo.java new file mode 100644 index 0000000..b711421 --- /dev/null +++ b/src/main/java/me/bobert/netneutrality/music/TrackInfo.java @@ -0,0 +1,72 @@ +package me.bobert.netneutrality.music;/* + * Copyright (c) anthorob + * + * https://discord.gg/qUa6zNFZsd + */ + +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import net.dv8tion.jda.api.entities.Member; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public class TrackInfo { + private final AudioTrack track; + private final Member member; + private final Set skips; + private static final Logger logger = LogManager.getLogger(QueueManager.class); + + public TrackInfo(AudioTrack track, Member member) { + this.track = track; + this.member = member; + this.skips = new HashSet<>(); + } + + public AudioTrack getTrack() { + return track; + } + + public Set getSkips() { + return skips; + } + + public void addSkip(Member member) { + if (!hasSkip(member)) { + logger.debug("VoteSkip: user={}, skip doesn't exist, before={}, after={}", member.getId(), skips.size(), skips.size() + 1); + skips.add(member.getId()); + } + } + + public boolean hasSkip(Member member) { + return skips.contains(member.getId()); + } + + public Member getRequester() { + return member; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TrackInfo trackInfo = (TrackInfo) o; + return track.equals(trackInfo.track); + } + + @Override + public int hashCode() { + return Objects.hash(track); + } + + @Override + public String toString() { + return "TrackInfo{" + + "track=" + track.getInfo().title + + ", member=" + member.getEffectiveName() + + ", skips=" + skips + + '}'; + } +} diff --git a/src/main/java/me/bobert/netneutrality/music/TrackLoadingHandler.java b/src/main/java/me/bobert/netneutrality/music/TrackLoadingHandler.java index 3c52c96..752774e 100644 --- a/src/main/java/me/bobert/netneutrality/music/TrackLoadingHandler.java +++ b/src/main/java/me/bobert/netneutrality/music/TrackLoadingHandler.java @@ -27,7 +27,7 @@ public class TrackLoadingHandler implements AudioLoadResultHandler { private final SourceFinder.AudioSourceType type; private final boolean silent; private final Guild guild; - private final TrackScheduler scheduler; + private final QueueManager queueManager; private final CommandContext context; public TrackLoadingHandler(CommandContext context, MusicManager manager, String identifier, SourceFinder.AudioSourceType type, boolean silent) { @@ -35,18 +35,17 @@ public class TrackLoadingHandler implements AudioLoadResultHandler { this.type = type; this.silent = silent; this.guild = manager.getGuild(); - this.scheduler = manager.getScheduler(); + this.queueManager = manager.getQueueManager(); this.context = context; } @Override public void trackLoaded(AudioTrack audioTrack) { - context.deleteMessage(); - logger.debug("Guild {}: track loaded: {}", guild.getId(), audioTrack.getIdentifier()); + context.deleteMessage(); if (MusicUtils.connect(context)) { - scheduler.getQueueManager().queue(audioTrack, context.getGuildUser()); + queueManager.queue(audioTrack, context.getGuildUser()); if (!silent) { context.reply(MessageFunction.buildAddingTrackMessage(audioTrack, context.getGuildUser(), type)); diff --git a/src/main/java/me/bobert/netneutrality/music/TrackScheduler.java b/src/main/java/me/bobert/netneutrality/music/TrackScheduler.java index 4294809..390f44c 100644 --- a/src/main/java/me/bobert/netneutrality/music/TrackScheduler.java +++ b/src/main/java/me/bobert/netneutrality/music/TrackScheduler.java @@ -12,21 +12,20 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason; import me.bobert.netneutrality.context.MusicChannelContext; import me.bobert.netneutrality.core.LogHandler; +import me.bobert.netneutrality.core.context.Context; import me.bobert.netneutrality.utils.MessageFunction; import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; -import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.entities.Member; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class TrackScheduler extends AudioEventAdapter { private static final Logger logger = LogManager.getLogger(TrackScheduler.class); - private final QueueManager queueManager; private final MusicManager manager; private final AudioPlayer player; private final Guild guild; - private MusicChannelContext context; + private Context context; private AudioTrack lastStuckTrack = null; public TrackScheduler(MusicManager manager) { @@ -52,17 +51,19 @@ public class TrackScheduler extends AudioEventAdapter { return guild; } - public MusicChannelContext getCurrentContext() { - return context; - } - - public synchronized void attachChannel(MessageChannel channel) { - if (channel instanceof GuildMessageChannel guildMessageChannel) { - this.context = new MusicChannelContext(guildMessageChannel); + public Member getDj() { + if (context != null) { + return context.getGuildUser(); } + + return null; } - public synchronized void detachTextChannel() { + public synchronized void attachContext(MusicChannelContext context) { + this.context = context; + } + + public synchronized void detachContext() { this.context = null; } @@ -128,7 +129,7 @@ public class TrackScheduler extends AudioEventAdapter { logger.debug("Trying to load stuck track again: {}", track.getIdentifier()); context.async("Current track is stuck, trying to load it again", asyncMessage -> { try { - QueueManager.TrackInfo info = queueManager.peekHeadOfQueue(); + TrackInfo info = queueManager.peekHeadOfQueue(); if (info != null && info.getTrack().getIdentifier().equals(track.getIdentifier())) { AudioTrack clone = track.makeClone(); long lastPosition = track.getPosition(); diff --git a/src/main/java/me/bobert/netneutrality/tasks/music/AddAllTracksTask.java b/src/main/java/me/bobert/netneutrality/tasks/music/AddAllTracksTask.java index f74d948..6793f98 100644 --- a/src/main/java/me/bobert/netneutrality/tasks/music/AddAllTracksTask.java +++ b/src/main/java/me/bobert/netneutrality/tasks/music/AddAllTracksTask.java @@ -41,13 +41,11 @@ public class AddAllTracksTask extends ButtonTask implements WithParent members = channel.getMembers().stream().filter(member -> !member.getId().equals(NetNeutrality.getSelf().getId())).toList(); - return members.isEmpty() || manager.getScheduler().getQueueManager().isEmpty(); + return members.isEmpty() || manager.getQueueManager().isEmpty(); } } diff --git a/src/main/java/me/bobert/netneutrality/utils/MessageFunction.java b/src/main/java/me/bobert/netneutrality/utils/MessageFunction.java index 4cf05ad..1c08a2f 100644 --- a/src/main/java/me/bobert/netneutrality/utils/MessageFunction.java +++ b/src/main/java/me/bobert/netneutrality/utils/MessageFunction.java @@ -18,13 +18,12 @@ import me.bobert.netneutrality.core.context.Context; import me.bobert.netneutrality.core.context.TaskContext; import me.bobert.netneutrality.exceptions.ContextException; import me.bobert.netneutrality.music.MusicManager; -import me.bobert.netneutrality.music.QueueManager; import me.bobert.netneutrality.music.SourceFinder; +import me.bobert.netneutrality.music.TrackInfo; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import org.apache.commons.lang3.time.DurationFormatUtils; import org.apache.logging.log4j.LogManager; @@ -110,37 +109,39 @@ public class MessageFunction { return message.build(); } - public static MessageEmbed buildViewQueueMessage(MusicManager manager, boolean currentlyPlaying) { - ArrayList tracks = manager.getScheduler().getQueueManager().getAllQueuedTrack(); + public static String buildViewQueueMessage(MusicManager manager) { + int limit = 15; + List tracks = manager.getQueueManager().getAllQueuedTracks(); AudioTrack current = manager.getCurrentlyPlaying(); - int numberofTracksShown = Math.min(tracks.size(), 10); + int numberofTracksShown = Math.min(tracks.size(), limit); - EmbedBuilder message = new EmbedBuilder(); - message.setTitle(String.format("Current queue (showing %d out of %d items):", numberofTracksShown, tracks.size())); - message.setColor(Color.BLUE); + StringBuilder message = new StringBuilder(); + message.append("Here is the current queue of the bot ") + .append("(showing ") + .append(numberofTracksShown) + .append(" out of ") + .append(tracks.size()) + .append(" items):\n"); int index = 0; for (AudioTrack track : tracks) { AudioTrackInfo info = track.getInfo(); - if (current != null && current.getInfo().title.equals(info.title) && currentlyPlaying) { - message.addField("Track #" + ++index + " (Currently playing)", info.title, false); + message.append("\n"); + if (current != null && current.getInfo().title.equals(info.title)) { + message.append("**").append(++index).append(". ").append(info.title).append("**"); } else { - message.addField("Track #" + ++index, info.title, false); + message.append(++index).append(". ").append(info.title); } - if (index == 10) break; + if (index == limit) break; } - message.setTimestamp(OffsetDateTime.now()); - - return message.build(); + return message.toString(); } public static MessageEmbed buildUserTracksMessage(MusicManager manager, Member member) { - List tracks = manager.getScheduler() - .getQueueManager() - .getQueueWithFilter(trackInfo -> member.equals(trackInfo.getRequester())); + List tracks = manager.getQueueManager().getQueueWithFilter(trackInfo -> member.equals(trackInfo.getRequester())); AudioTrack current = manager.getCurrentlyPlaying(); int numberofTracksShown = Math.min(tracks.size(), 10); @@ -149,7 +150,7 @@ public class MessageFunction { message.setColor(Color.BLUE); int index = 0; - for (QueueManager.TrackInfo track : tracks) { + for (TrackInfo track : tracks) { AudioTrackInfo info = track.getTrack().getInfo(); if (current != null && current.getInfo().title.equals(info.title)) { diff --git a/src/main/java/me/bobert/netneutrality/utils/MusicUtils.java b/src/main/java/me/bobert/netneutrality/utils/MusicUtils.java index e787cc0..8a9e3c4 100644 --- a/src/main/java/me/bobert/netneutrality/utils/MusicUtils.java +++ b/src/main/java/me/bobert/netneutrality/utils/MusicUtils.java @@ -5,23 +5,26 @@ package me.bobert.netneutrality.utils; * https://discord.gg/qUa6zNFZsd */ +import me.bobert.netneutrality.context.MusicChannelContext; import me.bobert.netneutrality.core.context.Context; import me.bobert.netneutrality.exceptions.ContextException; import me.bobert.netneutrality.music.MusicManager; import net.dv8tion.jda.api.entities.GuildVoiceState; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel; +import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; public class MusicUtils { public static boolean connect(Context context) { - return connect(context, false); + return connect(context, false, false); } - public static boolean connect(Context context, boolean skipChecks) { + public static boolean connect(Context context, boolean skipChecks, boolean checkOnly) { MusicManager manager = MusicManager.get(context.getGuild()); Member member = context.getGuildUser(); if (member == null) { + context.reply("Context doesn't have a Guild user, can't continue"); return false; } @@ -36,31 +39,16 @@ public class MusicUtils { return false; } - if (manager.isNotConnectedTo(audioChannel)) { + if (!checkOnly && manager.isNotConnectedTo(audioChannel)) { manager.connect(audioChannel); - manager.getScheduler().attachChannel(context.getChannel()); + manager.getScheduler().attachContext(new MusicChannelContext((GuildMessageChannel) context.getChannel(), context.getGuildUser())); } return true; } public static boolean canConnect(Context context) { - return canConnect(context, false); - } - - public static boolean canConnect(Context context, boolean skipChecks) { - MusicManager manager = MusicManager.get(context.getGuild()); - Member member = context.getGuildUser(); - if (member == null) { - return false; - } - - AudioChannel audioChannel = getVoiceChannel(context); - if (audioChannel == null) { - return false; - } - - return skipChecks || isUserDj(member) || (!manager.isConnected() || !manager.isNotConnectedTo(audioChannel)); + return connect(context, false, true); } public static boolean checkIfConnected(Context context) { @@ -85,23 +73,6 @@ public class MusicUtils { return true; } - public static boolean checkIfNotConnected(Context context) { - MusicManager manager = MusicManager.get(context.getGuild()); - - AudioChannel voiceChannel = getVoiceChannel(context); - if (voiceChannel == null) { - context.reply("You are not in a voice channel"); - return false; - } - - if (manager.isConnected()) { - context.reply("The bot is already in a voice channel"); - return false; - } - - return manager.isNotConnectedTo(voiceChannel); - } - public static AudioChannel getVoiceChannel(Context context) { GuildVoiceState memberVoiceState = context.getGuildUser().getVoiceState(); @@ -118,11 +89,12 @@ public class MusicUtils { public static boolean isUserDj(Member member) { MusicManager manager = MusicManager.get(member.getGuild()); + Member dj = manager.getScheduler().getDj(); - if (manager.isCurrentlyPlaying()) { - return manager.getRequesterOfCurrentTrack().equals(member); + if (manager.isCurrentlyPlaying() && dj != null) { + return dj.equals(member); } - return false; + return manager.getQueueSize() == 0 || !manager.isCurrentlyPlaying(); } }