223 lines
8.3 KiB
Java
223 lines
8.3 KiB
Java
package me.bobert.netneutrality.music;
|
|
|
|
/*
|
|
* Copyright (c) anthorob
|
|
*
|
|
* https://discord.gg/qUa6zNFZsd
|
|
*/
|
|
|
|
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
|
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
|
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
|
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 dev.lavalink.youtube.YoutubeSourceOptions;
|
|
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
|
import me.bobert.netneutrality.core.context.CommandContext;
|
|
import me.bobert.netneutrality.db.GSettings;
|
|
import me.bobert.netneutrality.db.service.GuildService;
|
|
import me.bobert.netneutrality.music.source.UdioAudioSourceManager;
|
|
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.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;
|
|
|
|
public class MusicManager {
|
|
|
|
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 final int baseVolume;
|
|
|
|
private MusicManager(Guild guild) {
|
|
this.guild = guild;
|
|
this.player = playerManager.createPlayer();
|
|
this.scheduler = new TrackScheduler(this);
|
|
this.baseVolume = Integer.parseInt(GuildService.get(guild).getGuildSettingService().getSetting(GSettings.MUSIC_VOLUME));
|
|
|
|
guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player));
|
|
player.addListener(scheduler);
|
|
|
|
managers.put(guild.getId(), this);
|
|
}
|
|
|
|
public static MusicManager get(Guild guild) {
|
|
if (managers.containsKey(guild.getId())) {
|
|
return managers.get(guild.getId());
|
|
} else {
|
|
return new MusicManager(guild);
|
|
}
|
|
}
|
|
|
|
public static void initPlayerManager() {
|
|
logger.debug("Initializing music player sources..");
|
|
|
|
String cipherUrl = Settings.getInstance().get("NETNEUTRALITY_CIPHER_URL");
|
|
String cipherPassword = Settings.getInstance().get("NETNEUTRALITY_CIPHER_PASSWORD");
|
|
YoutubeSourceOptions options = new YoutubeSourceOptions()
|
|
.setAllowSearch(true)
|
|
.setAllowDirectVideoIds(true)
|
|
.setAllowDirectPlaylistIds(true)
|
|
.setRemoteCipher(cipherUrl, cipherPassword, "");
|
|
playerManager.registerSourceManager(new YoutubeAudioSourceManager(options, YoutubeAudioSourceManager.DEFAULT_CLIENTS));
|
|
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);
|
|
}
|
|
|
|
public static void disconnectPlayers() {
|
|
for (MusicManager mm : managers.values()) {
|
|
mm.getQueueManager().clearQueue();
|
|
mm.player.destroy();
|
|
}
|
|
}
|
|
|
|
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);
|
|
} else {
|
|
throw new RuntimeException("Error connecting to voice channel");
|
|
}
|
|
}
|
|
|
|
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() {
|
|
return player.getPlayingTrack();
|
|
}
|
|
|
|
public synchronized boolean isCurrentlyPlaying() {
|
|
return player.getPlayingTrack() != null;
|
|
}
|
|
|
|
public synchronized void play(String query, CommandContext context) {
|
|
play(query, context, false);
|
|
}
|
|
|
|
public synchronized void play(String query, CommandContext context, boolean silent) {
|
|
logger.debug("Guild {}: request to play '{}' by user {}", guild.getId(), query, context.getGuildUser().getId());
|
|
|
|
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;
|
|
}
|
|
|
|
TrackLoadingHandler loadingHandler = new TrackLoadingHandler(context, this, identifier, type, silent);
|
|
playerManager.loadItemOrdered(this, identifier, loadingHandler);
|
|
}
|
|
}
|
|
|
|
public synchronized void stopTrack() {
|
|
player.stopTrack();
|
|
}
|
|
|
|
public synchronized CommandExecutionResult resume() {
|
|
return getQueueManager().resume();
|
|
}
|
|
|
|
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.warn("No tracks are currently playing");
|
|
}
|
|
|
|
TrackInfo info = getQueueManager().peekHeadOfQueue();
|
|
if (info == null) {
|
|
return CommandExecutionResult.warn("Queue is empty");
|
|
}
|
|
|
|
// Minus the bot itself
|
|
int connected = audioChannel.getMembers().size() - 1;
|
|
|
|
if (connected < 3) {
|
|
getQueueManager().skip();
|
|
|
|
return CommandExecutionResult.info("Skipping current track since not enough people are connected to the voice channel.");
|
|
}
|
|
|
|
double needed = connected / 2.1;
|
|
|
|
info.addSkip(context.getGuildUser());
|
|
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 getQueueManager().skip();
|
|
}
|
|
|
|
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) {
|
|
player.setVolume(volume);
|
|
}
|
|
|
|
public int getQueueSize() {
|
|
return getQueueManager().getQueueSize();
|
|
}
|
|
}
|