Version 3.0

This commit is contained in:
anthorob committed 2025-03-09 20:08:43 +00:00
1 parent 5fb29ea4ed
commit 1242118b0d
174 files changed
+8366 -3263

No files matched your search

@@ -13,46 +13,41 @@ import com.sedmelluq.discord.lavaplayer.source.http.HttpAudioSourceManager;
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import dev.lavalink.youtube.YoutubeAudioSourceManager;
import me.bobert.netneutrality.command.CommandExecutionResult;
import me.bobert.netneutrality.core.GuildManager;
import me.bobert.netneutrality.core.LogHandler;
import me.bobert.netneutrality.core.command.CommandExecutionResult;
import me.bobert.netneutrality.core.context.CommandContext;
import me.bobert.netneutrality.core.thread.ThreadManager;
import me.bobert.netneutrality.db.GSettings;
import me.bobert.netneutrality.exceptions.CommandExecutionException;
import me.bobert.netneutrality.db.service.GuildService;
import me.bobert.netneutrality.music.source.UdioAudioSourceManager;
import me.bobert.netneutrality.thread.MusicManagerCleanupThread;
import me.bobert.netneutrality.thread.MusicPlayerAutoDisconnectThread;
import me.bobert.netneutrality.thread.ThreadManager;
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.concrete.VoiceChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class MusicManager {
private final static Logger logger = LogManager.getLogger(MusicManager.class);
private final static Map<String, MusicManager> managers = new ConcurrentHashMap<>();
private final static ScheduledExecutorService executor = ThreadManager.getMusicExecutor();
private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
private static final Logger logger = LogManager.getLogger(MusicManager.class);
private static final Map<String, MusicManager> managers = new ConcurrentHashMap<>();
private static final AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
private final Guild guild;
private final AudioPlayer player;
private final TrackScheduler scheduler;
private ScheduledFuture<?> autoDisconnectThread;
private final int baseVolume;
private MusicManager(Guild guild) {
this.guild = guild;
this.player = playerManager.createPlayer();
this.scheduler = new TrackScheduler(this);
this.baseVolume = Integer.parseInt(GuildManager.getManager(guild).getGuildConfigManager().getSetting(GSettings.MUSIC_VOLUME));
this.baseVolume = Integer.parseInt(GuildService.get(guild).getGuildSettingService().getSetting(GSettings.MUSIC_VOLUME));
guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player));
player.addListener(scheduler);
@@ -73,28 +68,70 @@ public class MusicManager {
playerManager.registerSourceManager(SoundCloudAudioSourceManager.createDefault());
playerManager.registerSourceManager(new UdioAudioSourceManager());
playerManager.registerSourceManager(new HttpAudioSourceManager());
String po = Settings.getInstance().get("NETNEUTRALITY_PO_TOKEN");
String visitor = Settings.getInstance().get("NETNEUTRALITY_VISITOR_DATA");
dev.lavalink.youtube.clients.Web.setPoTokenAndVisitorData(po, visitor);
ThreadManager.getScheduledExecutor().scheduleWithFixedDelay(new MusicPlayerAutoDisconnectThread(), 15, 15, TimeUnit.MINUTES);
ThreadManager.getScheduledExecutor().scheduleWithFixedDelay(new MusicManagerCleanupThread(), 1, 1, TimeUnit.HOURS);
}
public boolean isNotConnectedTo(VoiceChannel vChannel) {
return vChannel == null || !vChannel.equals(guild.getAudioManager().getConnectedChannel());
public static void disconnectPlayers() {
for (MusicManager mm : managers.values()) {
mm.getQueueManager().clearQueue();
mm.player.destroy();
}
}
public synchronized void connect(VoiceChannel vChannel) {
if (vChannel != null && isNotConnectedTo(vChannel)) {
logger.debug("Guild {}: connecting to voice channel {}", vChannel.getGuild().getId(), vChannel.getId());
guild.getAudioManager().openAudioConnection(vChannel);
public static Collection<MusicManager> getManagers() {
return managers.values();
}
public TrackScheduler getScheduler() {
return scheduler;
}
public QueueManager getQueueManager() {
return scheduler.getQueueManager();
}
public AudioPlayer getPlayer() {
return player;
}
public Guild getGuild() {
return guild;
}
public synchronized boolean isNotConnectedTo(AudioChannel vChannel) {
AudioChannel current = guild.getAudioManager().getConnectedChannel();
return vChannel == null || current == null || !vChannel.getId().equals(current.getId());
}
public synchronized void connect(AudioChannel audioChannel) {
if (audioChannel != null) {
logger.debug("Guild {}: connecting to voice channel {}", audioChannel.getGuild().getId(), audioChannel.getId());
guild.getAudioManager().openAudioConnection(audioChannel);
guild.getAudioManager().setSelfDeafened(true);
player.setVolume(baseVolume);
if (autoDisconnectThread == null)
autoDisconnectThread = executor.scheduleWithFixedDelay(new MusicPlayerAutoDisconnectThread(this), 240, 240, TimeUnit.SECONDS);
} else {
throw new RuntimeException("Error connecting to voice channel");
}
}
public boolean isConnected() {
return guild != null && guild.getAudioManager().getConnectedChannel() != null;
public synchronized void disconnect() {
if (guild.getAudioManager().getConnectedChannel() != null) {
logger.debug("Guild {}: disconnecting from voice channel {}", guild.getId(), guild.getAudioManager().getConnectedChannel().getId());
player.stopTrack();
guild.getAudioManager().closeAudioConnection();
}
scheduler.detachContext();
}
public synchronized boolean isConnected() {
return guild.getAudioManager().getConnectedChannel() != null;
}
public synchronized AudioTrack getCurrentlyPlaying() {
@@ -105,81 +142,22 @@ 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();
public synchronized void play(String query, CommandContext context) {
play(query, context, false);
}
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, boolean needToBeConnected, boolean silent) {
public synchronized void play(String query, CommandContext context, boolean silent) {
logger.debug("Guild {}: request to play '{}' by user {}", guild.getId(), query, context.getGuildUser().getId());
Member member = context.getGuildUser();
MessageChannel channel = context.getChannel();
if (MusicUtils.canConnect(context)) {
SourceFinder.AudioSourceType type = SourceFinder.getSource(query);
String identifier = SourceFinder.getIdentifier(query);
if (identifier == null) {
context.reply("No source found to play the given url");
return;
}
if (member.getVoiceState() == null) {
logger.error("Guild {}: Voice state is null", guild.getId());
context.replyToMessage("Voice state is null, something has gone terribly wrong.");
LogHandler.log(new CommandExecutionException("Voice state is null", context, null));
return;
}
if (!member.getVoiceState().inAudioChannel()) {
context.replyToMessage("You are not in a voice channel");
return;
}
VoiceChannel vChannel = (VoiceChannel) member.getVoiceState().getChannel();
if (needToBeConnected && isNotConnectedTo(vChannel)) {
context.replyToMessage("The player is not in your voice channel");
return;
}
if (isNotConnectedTo(vChannel)) {
connect(vChannel);
scheduler.attachTextChannel(channel);
}
SourceFinder.AudioSourceType type = SourceFinder.getSource(query);
String identifier = SourceFinder.getIdentifier(query);
if (identifier != null) {
TrackLoadingHandler loadingHandler = new TrackLoadingHandler(context, this, identifier, type, silent);
playerManager.loadItemOrdered(this, identifier, loadingHandler);
}
}
@@ -188,30 +166,32 @@ public class MusicManager {
player.stopTrack();
}
public synchronized CommandExecutionResult voteSkip(CommandContext context) {
VoiceChannel voiceChannel = (VoiceChannel) guild.getAudioManager().getConnectedChannel();
public synchronized CommandExecutionResult resume() {
return getQueueManager().resume();
}
if (voiceChannel == null) {
return CommandExecutionResult.none();
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");
}
if (!isCurrentlyPlaying()) {
return CommandExecutionResult.none();
return CommandExecutionResult.warn("No tracks are currently playing");
}
QueueManager.TrackInfo info = scheduler.getQueueManager().peekHeadOfQueue();
TrackInfo info = getQueueManager().peekHeadOfQueue();
if (info == null) {
return CommandExecutionResult.none();
return CommandExecutionResult.warn("Queue is empty");
}
// Minus the bot itself
int connected = voiceChannel.getMembers().size() - 1;
int connected = audioChannel.getMembers().size() - 1;
if (connected < 3) {
context.reply("Skipping current track since not enough people are connected to the voice channel.");
scheduler.getQueueManager().skip();
getQueueManager().skip();
return CommandExecutionResult.none();
return CommandExecutionResult.info("Skipping current track since not enough people are connected to the voice channel.");
}
double needed = connected / 2.1;
@@ -220,12 +200,13 @@ 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();
} else {
context.reply("Adding your vote to skip the current track. Current votes: %d/%d", info.getSkips().size(), (int) Math.ceil(needed));
return getQueueManager().skip();
}
return CommandExecutionResult.none();
return CommandExecutionResult.success(String.format("Adding your vote to skip the current track. Current votes: %d/%d",
info.getSkips().size(),
(int) Math.ceil(needed))
);
}
public synchronized void setVolume(int volume) {
@@ -233,10 +214,6 @@ public class MusicManager {
}
public int getQueueSize() {
return scheduler.getQueueManager().getQueueSize();
}
public TrackScheduler getScheduler() {
return scheduler;
return getQueueManager().getQueueSize();
}
}