Improve music manager and add more debug messages
This commit is contained in:
1 parent
7bfadb05f7
commit
8325256e5e
35 files changed
+557
-198
No files matched your search
@@ -18,6 +18,8 @@ import netneutrality.thread.BaseThreadFactory;
|
||||
import netneutrality.thread.ShutdownThread;
|
||||
import netneutrality.thread.ThreadManager;
|
||||
import netneutrality.utils.Settings;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -38,8 +40,12 @@ public class NetNeutrality {
|
||||
options.setDebug(env.equals("dev"));
|
||||
});
|
||||
|
||||
initJDA();
|
||||
if ("dev".equals(env)) {
|
||||
Configurator.setLevel("net.dv8tion.jda", Level.DEBUG);
|
||||
}
|
||||
|
||||
DBController.init();
|
||||
initJDA();
|
||||
CommandManager.init();
|
||||
MusicManager.initPlayerManager();
|
||||
jda.addEventListener(new MessageReceivedHandler(), new EditHandler(), new ServerJoinHandler());
|
||||
|
||||
@@ -86,14 +86,14 @@ public class BitcoinPriceCommand extends AbstractCommand {
|
||||
try {
|
||||
WebModule http = new WebModule(String.format("%s?fsym=%s&tsyms=%s", baseURL, crypto, finalCurrency.toUpperCase())).request();
|
||||
JSONObject json = http.getAsObject();
|
||||
if (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error")) {
|
||||
if (json.isEmpty() || (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error"))) {
|
||||
t.editMessage(String.format("Failed getting price of %s", crypto)).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
price = dollarFormat.format(json.getDouble(finalCurrency));
|
||||
t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
|
||||
} catch (IOException | JSONException | IllegalArgumentException | ArithmeticException e) {
|
||||
} catch (JSONException | IllegalArgumentException | ArithmeticException e) {
|
||||
t.editMessage(String.format("Error getting price of %s!", crypto)).queue();
|
||||
LogHandler.log(e);
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public class CryptoPriceCommand extends AbstractCommand {
|
||||
try {
|
||||
WebModule http = new WebModule(String.format("%s?fsym=%s&tsyms=%s", baseURL, crypto, finalCurrency.toUpperCase())).request();
|
||||
JSONObject json = http.getAsObject();
|
||||
if (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error")) {
|
||||
if (json.isEmpty() || (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error"))) {
|
||||
t.editMessage("Crypto doesn't exist.. yet").queue();
|
||||
return;
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class CryptoPriceCommand extends AbstractCommand {
|
||||
price = dollarFormat.format(json.getDouble(finalCurrency));
|
||||
t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
|
||||
|
||||
} catch (IOException | JSONException | IllegalArgumentException | ArithmeticException e) {
|
||||
} catch (JSONException | IllegalArgumentException | ArithmeticException e) {
|
||||
t.editMessage(String.format("Error getting price of %s!", crypto)).queue();
|
||||
LogHandler.log(e);
|
||||
}
|
||||
|
||||
@@ -86,14 +86,14 @@ public class EthereumPriceCommand extends AbstractCommand {
|
||||
try {
|
||||
WebModule http = new WebModule(String.format("%s?fsym=%s&tsyms=%s", baseURL, crypto, finalCurrency.toUpperCase())).request();
|
||||
JSONObject json = http.getAsObject();
|
||||
if (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error")) {
|
||||
if (json.isEmpty() || (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error"))) {
|
||||
t.editMessage(String.format("Failed getting price of %s", crypto)).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
price = dollarFormat.format(json.getDouble(finalCurrency));
|
||||
t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
|
||||
} catch (IOException | JSONException | IllegalArgumentException e) {
|
||||
} catch (JSONException | IllegalArgumentException e) {
|
||||
t.editMessage(String.format("Error getting price of %s!", crypto)).queue();
|
||||
LogHandler.log(e);
|
||||
}
|
||||
|
||||
@@ -86,14 +86,14 @@ public class LitecoinPriceCommand extends AbstractCommand {
|
||||
try {
|
||||
WebModule http = new WebModule(String.format("%s?fsym=%s&tsyms=%s", baseURL, crypto, finalCurrency.toUpperCase())).request();
|
||||
JSONObject json = http.getAsObject();
|
||||
if (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error")) {
|
||||
if (json.isEmpty() || (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error"))) {
|
||||
t.editMessage(String.format("Failed getting price of %s", crypto)).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
price = dollarFormat.format(json.getDouble(finalCurrency));
|
||||
t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
|
||||
} catch (IOException | JSONException | IllegalArgumentException | ArithmeticException e) {
|
||||
} catch (JSONException | IllegalArgumentException | ArithmeticException e) {
|
||||
t.editMessage(String.format("Error getting price of %s!", crypto)).queue();
|
||||
LogHandler.log(e);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class BlacklistCommand extends AbstractCommand {
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
String[] args = context.getArgumentsAsArray();
|
||||
DBBlacklist controller = DBController.get("blacklist", DBBlacklist.class);
|
||||
DBBlacklist controller = DBController.get(DBBlacklist.class);
|
||||
|
||||
if (args.length > 0 && args.length < 3) {
|
||||
String word = (args.length == 2 ? args[1] : "");
|
||||
|
||||
@@ -79,8 +79,11 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
|
||||
int num = Integer.parseInt(context.getArg(0));
|
||||
|
||||
if (num > 0) {
|
||||
player.removeFromQueue(num);
|
||||
context.reply("Removing track #%d from the queue", num);
|
||||
if (player.removeFromQueue(num)) {
|
||||
context.reply("Removed track #%d from the queue", num);
|
||||
} else {
|
||||
context.reply("Error while removing track #%d from the queue", num);
|
||||
}
|
||||
} else {
|
||||
context.reply("Number out of range");
|
||||
}
|
||||
|
||||
@@ -60,6 +60,10 @@ public class JoinCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
VoiceChannel vChannel = context.getGuildUser().getVoiceState().getChannel();
|
||||
player.connect(vChannel);
|
||||
if (vChannel != null) {
|
||||
player.connect(vChannel);
|
||||
context.reply("Joining current voice channel");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,7 @@ public class LeaveCommand extends AbstractMusicCommand {
|
||||
|
||||
if (MusicUtils.checkIfConnected(player, context)) {
|
||||
player.leave();
|
||||
context.reply("Leaving voice channel and clearing queue");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,6 @@ import netneutrality.command.CommandUsage;
|
||||
import netneutrality.core.context.CommandContext;
|
||||
import netneutrality.music.MusicManager;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PlayCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
@@ -47,7 +45,6 @@ public class PlayCommand extends AbstractMusicCommand {
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
MusicManager player = MusicManager.get(context.getGuild());
|
||||
context.getMessage().delete().queueAfter(1, TimeUnit.SECONDS);
|
||||
|
||||
if (context.getArgs().length > 0) {
|
||||
player.play(context.getMessageText(), context, false, false);
|
||||
|
||||
@@ -52,11 +52,14 @@ public class SkipCommand extends AbstractMusicCommand {
|
||||
try {
|
||||
int skips = Integer.parseInt(context.getArg(0));
|
||||
player.skip(skips);
|
||||
|
||||
context.reply("Skipping %s track%s", skips, (skips > 1 ? "s" : ""));
|
||||
} catch (NumberFormatException e) {
|
||||
context.reply("Please enter how many track(s) to skip");
|
||||
}
|
||||
} else {
|
||||
player.skip(1);
|
||||
context.reply("Skipping current track");
|
||||
}
|
||||
} else {
|
||||
player.voteSkip(context);
|
||||
|
||||
@@ -46,6 +46,7 @@ public class StopCommand extends AbstractMusicCommand {
|
||||
|
||||
if (MusicUtils.checkIfConnected(player, context) && MusicUtils.isDj(player, context)) {
|
||||
player.stopTrack();
|
||||
context.reply("Stopping current track");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public class DatabaseCommand extends AbstractCommand {
|
||||
|
||||
if (args.length > 1) {
|
||||
|
||||
OLogMessage message = DBController.get("message", DBMessage.class).getMessage(args[1]);
|
||||
OLogMessage message = DBController.get(DBMessage.class).getMessage(args[1]);
|
||||
if (message != null) {
|
||||
EmbedBuilder embed = new EmbedBuilder();
|
||||
embed.setColor(Color.BLUE);
|
||||
@@ -88,7 +88,7 @@ public class DatabaseCommand extends AbstractCommand {
|
||||
//TODO: cached user lol xd
|
||||
User user = context.getJDA().getUserById(args[1]);
|
||||
if (user != null) {
|
||||
List<OLogMessage> messages = DBController.get("message", DBMessage.class)
|
||||
List<OLogMessage> messages = DBController.get(DBMessage.class)
|
||||
.getMessagesFromUser(user.getName(), context.getGuild().getName(), 10);
|
||||
EmbedBuilder embed = new EmbedBuilder();
|
||||
embed.setColor(Color.BLUE);
|
||||
|
||||
@@ -49,8 +49,8 @@ public class CommandManager {
|
||||
commands.put(command.getCommandName(), command);
|
||||
}
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||
LogHandler.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ public class GuildManager {
|
||||
|
||||
public void checkAndLogMessage(Message message, Member member, TextChannel channel) {
|
||||
if (isLoggingEnabled()) {
|
||||
ThreadManager.getExecutor("log-messages").submit(() -> DBController.get("message", DBMessage.class).log(this, channel, member, message));
|
||||
ThreadManager.getExecutor("log-messages").submit(() -> DBController.get(DBMessage.class).log(this, channel, member, message));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import netneutrality.utils.UserFunction;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CommandContext {
|
||||
|
||||
@@ -153,6 +154,18 @@ public class CommandContext {
|
||||
}
|
||||
}
|
||||
|
||||
public void replyToMessage(String msg) {
|
||||
if (channel != null && channel.canTalk() && message != null) {
|
||||
replyToMessage(new MessageBuilder(msg).build());
|
||||
}
|
||||
}
|
||||
|
||||
public void replyToMessage(Message msg) {
|
||||
if (channel != null && channel.canTalk() && message != null) {
|
||||
message.reply(msg).queue();
|
||||
}
|
||||
}
|
||||
|
||||
public void replyPrivate(String msg) {
|
||||
replyPrivate(new MessageBuilder(msg).build());
|
||||
}
|
||||
@@ -169,6 +182,22 @@ public class CommandContext {
|
||||
user.openPrivateChannel().flatMap(channel -> channel.sendMessageEmbeds(embeds)).queue();
|
||||
}
|
||||
|
||||
public void deleteMessage() {
|
||||
if (message != null) {
|
||||
message.delete().queueAfter(1, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMessageFromOwner() {
|
||||
return member.isOwner();
|
||||
}
|
||||
|
||||
public boolean isMessageFromCreator() {
|
||||
String creatorId = Settings.getInstance().getCreatorId();
|
||||
|
||||
return creatorId.equals(member.getId());
|
||||
}
|
||||
|
||||
public void dispatch(AbstractCommand command) {
|
||||
this.command = command;
|
||||
//TODO: Add usage check
|
||||
|
||||
@@ -14,13 +14,6 @@ public abstract class AbstractController {
|
||||
|
||||
protected SessionFactory sessionFactory;
|
||||
|
||||
/**
|
||||
* The controller name to be used in {@link DBController#get(String controller, Class returnType)} method
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public abstract String getControllerName();
|
||||
|
||||
public AbstractController() {
|
||||
sessionFactory = SessionManager.getSessionFactory();
|
||||
}
|
||||
|
||||
@@ -8,86 +8,32 @@ package netneutrality.db;
|
||||
*/
|
||||
|
||||
import netneutrality.core.SessionManager;
|
||||
import netneutrality.thread.ThreadManager;
|
||||
import org.reflections.Reflections;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* When creating a controller, all database actions must be executed in another thread using an executor. One is provided in the {@link ThreadManager} class
|
||||
* A simple thread can't be used in this case because overlapping actions might happen and won't be executed.
|
||||
*/
|
||||
public class DBController {
|
||||
|
||||
/**
|
||||
* A map that contains all the controllers currently loaded
|
||||
*/
|
||||
private final static HashMap<String, AbstractController> controllers = new HashMap<>();
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DBController.class);
|
||||
|
||||
/**
|
||||
* @param controller The name of the controller as defined in the {@link AbstractController#getControllerName()}'s method
|
||||
* @return {@link AbstractController} The class with an AbstractController type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T get(String controller, Class<T> returnType) {
|
||||
public static <T> T get(Class<T> returnType) {
|
||||
if (returnType == null)
|
||||
throw new IllegalArgumentException("return type is null");
|
||||
|
||||
if (controllers.isEmpty())
|
||||
init();
|
||||
|
||||
if (controllers.containsKey(controller)) {
|
||||
return (T) controllers.get(controller);
|
||||
} else
|
||||
throw new RuntimeException("Error getting database controller");
|
||||
try {
|
||||
return returnType.getConstructor().newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
SessionManager.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional, will be called if the method {@link #get(String, Class) get()} is used
|
||||
*/
|
||||
|
||||
public static void init() {
|
||||
if (controllers.isEmpty())
|
||||
loadControllers();
|
||||
SessionManager.getSessionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all the controllers which extends {@link AbstractController}
|
||||
*/
|
||||
private static void loadControllers() {
|
||||
//TODO: to delete
|
||||
logger.info("Loading databases controllers..");
|
||||
|
||||
Reflections reflections = new Reflections("netneutrality.db.controllers");
|
||||
Set<Class<? extends AbstractController>> classes = reflections.getSubTypesOf(AbstractController.class);
|
||||
|
||||
for (Class<? extends AbstractController> s : classes) {
|
||||
try {
|
||||
if (Modifier.isAbstract(s.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AbstractController c = s.getConstructor().newInstance();
|
||||
|
||||
if (!controllers.containsKey(c.getControllerName())) {
|
||||
controllers.put(c.getControllerName(), c);
|
||||
logger.debug("Loaded controller: " + c.getControllerName());
|
||||
}
|
||||
|
||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -128,9 +128,4 @@ public class DBBlacklist extends AbstractController {
|
||||
session.close();
|
||||
return blacklist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getControllerName() {
|
||||
return "blacklist";
|
||||
}
|
||||
}
|
||||
@@ -96,10 +96,4 @@ public class DBMessage extends AbstractController {
|
||||
return message.getMessage();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getControllerName() {
|
||||
return "message";
|
||||
}
|
||||
}
|
||||
@@ -46,8 +46,8 @@ public class EditHandler extends ListenerAdapter {
|
||||
TextChannel channel = event.getGuild().getTextChannelById(guildEntity.getLogChannel());
|
||||
|
||||
if (channel != null) {
|
||||
String originalMessage = DBController.get("message", DBMessage.class).getMessageString(event.getMessage().getId());
|
||||
DBController.get("message", DBMessage.class).logEdit(event.getMessage().getId(), event.getMessage().getContentDisplay());
|
||||
String originalMessage = DBController.get(DBMessage.class).getMessageString(event.getMessage().getId());
|
||||
DBController.get(DBMessage.class).logEdit(event.getMessage().getId(), event.getMessage().getContentDisplay());
|
||||
|
||||
channel.sendMessageEmbeds(MessageFunction.buildEditMessage(event.getMember(), event.getMessage(), originalMessage)).queue();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package netneutrality.http;
|
||||
|
||||
import io.sentry.Breadcrumb;
|
||||
import io.sentry.Sentry;
|
||||
import netneutrality.core.LogHandler;
|
||||
import okhttp3.*;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@@ -144,11 +145,17 @@ public class WebModule {
|
||||
/**
|
||||
* @return the response as a JSONObject
|
||||
*/
|
||||
public JSONObject getAsObject() throws JSONException, IOException {
|
||||
public JSONObject getAsObject() {
|
||||
if (response == null)
|
||||
throw new RuntimeException("Request has not been sent");
|
||||
|
||||
return new JSONObject(response.body().string());
|
||||
|
||||
try {
|
||||
ResponseBody body = response.body();
|
||||
return new JSONObject(body.string());
|
||||
} catch (IOException | NullPointerException e) {
|
||||
LogHandler.log(e);
|
||||
return new JSONObject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,16 +21,14 @@ import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
||||
import netneutrality.core.GuildManager;
|
||||
import netneutrality.core.LogHandler;
|
||||
import netneutrality.core.context.CommandContext;
|
||||
import netneutrality.exceptions.CommandErrorException;
|
||||
import netneutrality.music.loadable.LoadableSong;
|
||||
import netneutrality.thread.MusicPlayerAutoDisconnectThread;
|
||||
import netneutrality.thread.ThreadManager;
|
||||
import netneutrality.utils.MessageFunction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
@@ -45,21 +43,19 @@ public class MusicManager {
|
||||
private final static Map<String, MusicManager> managers = new ConcurrentHashMap<>();
|
||||
private final static ScheduledExecutorService executor = (ScheduledExecutorService) ThreadManager.getExecutor("music", ThreadManager.ExecutorType.SCHEDULED);
|
||||
|
||||
private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
|
||||
private final Guild guild;
|
||||
private final AudioPlayer player;
|
||||
private final AudioPlayerManager playerManager;
|
||||
private final TrackScheduler scheduler;
|
||||
private ScheduledFuture<?> autoDisconnectThread;
|
||||
private final int baseVolume;
|
||||
|
||||
private MusicManager(Guild guild) {
|
||||
this.guild = guild;
|
||||
this.playerManager = new DefaultAudioPlayerManager();
|
||||
this.player = playerManager.createPlayer();
|
||||
this.scheduler = new TrackScheduler(player, guild);
|
||||
this.baseVolume = Integer.parseInt(GuildManager.getManager(guild).getSetting(GuildManager.Settings.MUSIC_VOLUME));
|
||||
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player));
|
||||
player.addListener(scheduler);
|
||||
|
||||
@@ -75,6 +71,8 @@ public class MusicManager {
|
||||
}
|
||||
|
||||
public static void initPlayerManager() {
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
|
||||
YoutubeHttpContextFilter.setPAPISID(netneutrality.utils.Settings.getInstance().get("BOT_PAPISID", ""));
|
||||
YoutubeHttpContextFilter.setPSID(netneutrality.utils.Settings.getInstance().get("BOT_PSID", ""));
|
||||
}
|
||||
@@ -85,6 +83,7 @@ public class MusicManager {
|
||||
|
||||
public synchronized void connect(VoiceChannel vChannel) {
|
||||
if (vChannel != null && !isConnectedTo(vChannel)) {
|
||||
logger.debug("Guild {}: connecting to voice channel {}", vChannel.getGuild().getId(), vChannel.getId());
|
||||
guild.getAudioManager().openAudioConnection(vChannel);
|
||||
guild.getAudioManager().setSelfDeafened(true);
|
||||
player.setVolume(baseVolume);
|
||||
@@ -124,6 +123,7 @@ public class MusicManager {
|
||||
|
||||
public synchronized void leave() {
|
||||
if (isConnected()) {
|
||||
logger.debug("Guild {}: leaving voice channel {}", guild.getId(), guild.getAudioManager().getConnectedChannel().getId());
|
||||
player.stopTrack();
|
||||
guild.getAudioManager().closeAudioConnection();
|
||||
}
|
||||
@@ -155,6 +155,100 @@ public class MusicManager {
|
||||
public synchronized void play(String url, CommandContext context, boolean needToBeConnected, boolean silent) {
|
||||
Member member = context.getGuildUser();
|
||||
TextChannel channel = context.getChannel();
|
||||
logger.debug("Guild {}: request to play by user {}, string=[{}]", guild.getId(), context.getGuildUser().getId(), url);
|
||||
|
||||
if (member.getVoiceState() == null) {
|
||||
context.deleteMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!member.getVoiceState().inVoiceChannel()) {
|
||||
context.reply("You are not in a voice channel");
|
||||
context.deleteMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
VoiceChannel vChannel = member.getVoiceState().getChannel();
|
||||
if (needToBeConnected && !isConnectedTo(vChannel)) {
|
||||
context.reply("The player is not in your voice channel");
|
||||
context.deleteMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isConnectedTo(vChannel)) {
|
||||
connect(vChannel);
|
||||
}
|
||||
|
||||
String identifier = SourceFinder.getIdentifier(url);
|
||||
scheduler.getTopicManager().attachTextChannel(channel);
|
||||
|
||||
if (identifier != null) {
|
||||
playerManager.loadItemOrdered(this, identifier, new AudioLoadResultHandler() {
|
||||
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack audioTrack) {
|
||||
logger.debug("Guild {}: track loaded: {}", guild.getId(), identifier);
|
||||
context.deleteMessage();
|
||||
|
||||
scheduler.getQueueManager().queue(audioTrack, member);
|
||||
|
||||
if (!silent) {
|
||||
//context.replyToMessage("Added track to queue");
|
||||
context.reply(MessageFunction.buildAddingTrackMessage(audioTrack, member, identifier));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist audioPlaylist) {
|
||||
logger.debug("Guild {}: playlist loaded: {}", guild.getId(), identifier);
|
||||
context.deleteMessage();
|
||||
|
||||
if (audioPlaylist.isSearchResult()) {
|
||||
AudioTrack track = audioPlaylist.getTracks().get(0);
|
||||
scheduler.getQueueManager().queue(track, member);
|
||||
|
||||
if (!silent) {
|
||||
//context.replyToMessage(new MessageBuilder("Added track to queue: ").append(String.format("https://youtu.be/%s", track.getIdentifier())).build());
|
||||
context.reply(MessageFunction.buildAddingTrackMessage(track, member, String.format("https://youtu.be/%s", track.getIdentifier())));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!silent) {
|
||||
//context.replyToMessage("Added playlist to queue");
|
||||
context.reply(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, member, identifier));
|
||||
}
|
||||
|
||||
for (AudioTrack track : audioPlaylist.getTracks()) {
|
||||
synchronized (scheduler.getQueueManager().getQueue()) {
|
||||
scheduler.getQueueManager().queue(track, member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noMatches() {
|
||||
logger.debug("Guild {}: no matches for identifier {}", guild.getId(), identifier);
|
||||
context.replyToMessage("No matches found");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFailed(FriendlyException e) {
|
||||
logger.debug("Guild {}: load failed for identifier {}", guild.getId(), identifier, e);
|
||||
context.replyToMessage("Failed to load track: " + e.getMessage());
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
context.replyToMessage("No source found to play the given url");
|
||||
}
|
||||
}
|
||||
|
||||
public void play(List<LoadableSong> songs, CommandContext context, boolean needToBeConnected, boolean silent) {
|
||||
Member member = context.getGuildUser();
|
||||
TextChannel channel = context.getChannel();
|
||||
|
||||
if (member.getVoiceState() == null) {
|
||||
return;
|
||||
@@ -175,72 +269,89 @@ public class MusicManager {
|
||||
connect(vChannel);
|
||||
}
|
||||
|
||||
String identifier = SourceFinder.getIdentifier(url);
|
||||
scheduler.getTopicManager().attachTextChannel(channel);
|
||||
boolean fromOnlineSource = songs.size() > 1;
|
||||
|
||||
if (identifier != null) {
|
||||
for (LoadableSong song : songs) {
|
||||
String identifier = SourceFinder.getIdentifier(song.name());
|
||||
|
||||
playerManager.loadItemOrdered(this, identifier, new AudioLoadResultHandler() {
|
||||
if (identifier != null) {
|
||||
playerManager.loadItemOrdered(this, identifier, new AudioLoadResultHandler() {
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack track) {
|
||||
if (!fromOnlineSource) {
|
||||
logger.debug("Guild {}: track loaded: {}", guild.getId(), identifier);
|
||||
context.deleteMessage();
|
||||
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack audioTrack) {
|
||||
logger.debug("Found results for identifier: {}", identifier);
|
||||
scheduler.getQueueManager().queue(audioTrack, member);
|
||||
scheduler.getQueueManager().queue(track, member);
|
||||
|
||||
if (!silent) {
|
||||
channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(audioTrack, member, identifier)).queue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist audioPlaylist) {
|
||||
if (identifier.startsWith("ytsearch:")) {
|
||||
AudioTrack track = audioPlaylist.getTracks().get(0);
|
||||
logger.debug("Found results for identifier: {}", identifier);
|
||||
scheduler.getQueueManager().queue(track, member);
|
||||
|
||||
if (!silent) {
|
||||
channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(track, member, String.format("https://youtu.be/%s", track.getIdentifier()))).queue();
|
||||
}
|
||||
|
||||
} else {
|
||||
logger.debug("Found results for playlist identifier: {}", identifier);
|
||||
|
||||
if (!silent) {
|
||||
channel.sendMessageEmbeds(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, member, identifier)).queue();
|
||||
}
|
||||
|
||||
for (AudioTrack track : audioPlaylist.getTracks()) {
|
||||
synchronized (scheduler.getQueueManager().getQueue()) {
|
||||
scheduler.getQueueManager().queue(track, member);
|
||||
if (!silent) {
|
||||
//context.replyToMessage("Added track to queue");
|
||||
context.reply(MessageFunction.buildAddingTrackMessage(track, member, identifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noMatches() {
|
||||
context.reply("No matches found");
|
||||
}
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist playlist) {
|
||||
logger.debug("Guild {}: playlist loaded: {}", guild.getId(), identifier);
|
||||
|
||||
@Override
|
||||
public void loadFailed(FriendlyException e) {
|
||||
context.reply("Failed to load track: " + e.getMessage());
|
||||
LogHandler.log(e);
|
||||
}
|
||||
if (!playlist.getTracks().isEmpty()) {
|
||||
context.deleteMessage();
|
||||
|
||||
if (playlist.isSearchResult()) {
|
||||
AudioTrack track = playlist.getTracks().get(0);
|
||||
scheduler.getQueueManager().queue(track, member);
|
||||
|
||||
if (!silent && !fromOnlineSource) {
|
||||
//context.replyToMessage(new MessageBuilder("Added track to queue: ").append(String.format("https://youtu.be/%s", track.getIdentifier())).build());
|
||||
context.reply(MessageFunction.buildAddingTrackMessage(track, member, String.format("https://youtu.be/%s", track.getIdentifier())));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!silent && !fromOnlineSource) {
|
||||
//context.replyToMessage("Added playlist to queue");
|
||||
context.reply(MessageFunction.buildAddingPlaylistMessage(playlist, member, identifier));
|
||||
}
|
||||
|
||||
for (AudioTrack track : playlist.getTracks()) {
|
||||
synchronized (scheduler.getQueueManager().getQueue()) {
|
||||
scheduler.getQueueManager().queue(track, member);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.replyToMessage("Playlist is empty");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noMatches() {
|
||||
logger.debug("Guild {}: no matches for identifier {}", guild.getId(), identifier);
|
||||
|
||||
if (fromOnlineSource) {
|
||||
//TODO:
|
||||
}
|
||||
context.replyToMessage("No matches found");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFailed(FriendlyException e) {
|
||||
logger.debug("Guild {}: load failed for identifier {}", guild.getId(), identifier, e);
|
||||
context.replyToMessage("Failed to load track: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
context.replyToMessage("No source found to play the given url");
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
throw new CommandErrorException("No source found to play the given url", context, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public synchronized void removeFromQueue(int num) {
|
||||
if (num == 1) {
|
||||
skip(1);
|
||||
} else {
|
||||
scheduler.getQueueManager().removeFromQueue(num);
|
||||
}
|
||||
public synchronized boolean removeFromQueue(int index) {
|
||||
return scheduler.getQueueManager().removeFromQueue(index);
|
||||
}
|
||||
|
||||
public synchronized void stopTrack() {
|
||||
@@ -253,6 +364,7 @@ public class MusicManager {
|
||||
nbTrack = 1;
|
||||
}
|
||||
|
||||
logger.debug("Guild {}: skipping tracks, toSkip={}", guild.getId(), nbTrack);
|
||||
scheduler.getQueueManager().skipAndPlay(nbTrack);
|
||||
} else {
|
||||
leave();
|
||||
@@ -278,13 +390,14 @@ public class MusicManager {
|
||||
if (connected > 2) {
|
||||
double needed = connected / 2.1;
|
||||
|
||||
info.toggleSkip(context.getGuildUser());
|
||||
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) {
|
||||
context.reply("Skipping current track: %s", info.getTrack().getInfo().title);
|
||||
skip(1);
|
||||
} else {
|
||||
context.reply("Current skips: %d/%d", info.getSkips().size(), (int) Math.ceil(needed));
|
||||
context.reply("Adding your vote to skip the current track. Current votes: %d/%d", info.getSkips().size(), (int) Math.ceil(needed));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,8 @@ import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
@@ -20,6 +22,7 @@ public class QueueManager {
|
||||
private final AudioTrack track;
|
||||
private final Member member;
|
||||
private final Set<String> skips;
|
||||
private final Logger logger = LoggerFactory.getLogger(QueueManager.class);
|
||||
|
||||
public TrackInfo(AudioTrack track, Member member) {
|
||||
this.track = track;
|
||||
@@ -35,11 +38,21 @@ public class QueueManager {
|
||||
return skips;
|
||||
}
|
||||
|
||||
public void toggleSkip(Member member) {
|
||||
if (!hasSkip(member))
|
||||
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());
|
||||
else
|
||||
}
|
||||
}
|
||||
|
||||
public void toggleSkip(Member member) {
|
||||
if (hasSkip(member)) {
|
||||
logger.debug("VoteSkip: user={}, skip already exist, before={}, after={}", member.getId(), skips.size(), skips.size() - 1);
|
||||
skips.remove(member.getId());
|
||||
} else {
|
||||
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) {
|
||||
@@ -73,6 +86,7 @@ public class QueueManager {
|
||||
}
|
||||
}
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(QueueManager.class);
|
||||
private final AudioPlayer player;
|
||||
private final Guild guild;
|
||||
private final Deque<TrackInfo> queue;
|
||||
@@ -120,7 +134,8 @@ public class QueueManager {
|
||||
}
|
||||
|
||||
if (player.getPlayingTrack() == null) {
|
||||
player.startTrack(queue.peek().getTrack(), false);
|
||||
AudioTrack toPlay = (queue.peek() == null ? null : queue.peek().getTrack());
|
||||
player.startTrack(toPlay, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,9 +143,15 @@ public class QueueManager {
|
||||
public void nextTrack(AudioPlayer player) {
|
||||
synchronized (queue) {
|
||||
TrackInfo last = queue.poll();
|
||||
TrackInfo next = queue.peek();
|
||||
|
||||
if (queue.peek() != null) {
|
||||
player.startTrack(queue.peek().getTrack(), false);
|
||||
if (next != null) {
|
||||
if (last != null && last.getTrack().equals(next.getTrack())) {
|
||||
logger.debug("Guild {}: duplicate track in queue found, skipping to next. last={}, next={}", guild.getId(), last.getTrack().getIdentifier(), next.getTrack().getIdentifier());
|
||||
nextTrack(player);
|
||||
} else {
|
||||
player.startTrack(next.getTrack(), false);
|
||||
}
|
||||
} else {
|
||||
player.stopTrack();
|
||||
}
|
||||
@@ -159,7 +180,8 @@ public class QueueManager {
|
||||
|
||||
public void shuffle() {
|
||||
synchronized (queue) {
|
||||
if (queue.size() > 2) {
|
||||
if (queue.size() > 3) {
|
||||
logger.debug("Guild {}: shuffling queue", guild.getId());
|
||||
TrackInfo current = queue.poll();
|
||||
|
||||
ArrayList<TrackInfo> newQueue = new ArrayList<>(queue);
|
||||
@@ -174,13 +196,25 @@ public class QueueManager {
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeFromQueue(int index) {
|
||||
protected boolean removeFromQueue(int index) {
|
||||
synchronized (queue) {
|
||||
ArrayList<TrackInfo> newQueue = new ArrayList<>(queue);
|
||||
newQueue.remove(index - 1);
|
||||
if (queue.size() > 0 && index <= queue.size()) {
|
||||
logger.debug("Guild {}: removing index {} from queue", guild.getId(), index - 1);
|
||||
|
||||
queue.clear();
|
||||
queue.addAll(newQueue);
|
||||
if (index == 1) {
|
||||
skipAndPlay(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
ArrayList<TrackInfo> newQueue = new ArrayList<>(queue);
|
||||
newQueue.remove(index - 1);
|
||||
|
||||
queue.clear();
|
||||
queue.addAll(newQueue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,22 +9,18 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import netneutrality.core.GuildManager;
|
||||
import netneutrality.thread.ThreadManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TopicManager {
|
||||
|
||||
private final ScheduledExecutorService service;
|
||||
private final Guild guild;
|
||||
private TextChannel channel;
|
||||
private String originalTopic;
|
||||
|
||||
public TopicManager(Guild guild) {
|
||||
this.guild = guild;
|
||||
this.service = (ScheduledExecutorService) ThreadManager.getExecutor("topic-management", ThreadManager.ExecutorType.SCHEDULED);
|
||||
}
|
||||
|
||||
public Guild getGuild() {
|
||||
@@ -59,16 +55,24 @@ public class TopicManager {
|
||||
if (isEnabled() && channel != null) {
|
||||
|
||||
if (track == null) {
|
||||
LogManager.getLogger(TopicManager.class).debug("Resetting topic for channel [{}] in guild [{}]", channel.getId(), guild.getId());
|
||||
channel.getManager().setTopic(originalTopic).queueAfter(3, TimeUnit.SECONDS, service);
|
||||
LogManager.getLogger(TopicManager.class).debug("Guild {}: Resetting topic for channel {}", guild.getId(), channel.getId());
|
||||
channel.getManager().setTopic(originalTopic).queueAfter(5, TimeUnit.SECONDS);
|
||||
} else {
|
||||
channel.getManager().setTopic(":speaker: Now playing: " + track.getInfo().title).queueAfter(3, TimeUnit.SECONDS, service);
|
||||
LogManager.getLogger(TopicManager.class).debug("Guild {}: Setting topic for channel {} to [{}]", guild.getId(), channel.getId(), track.getInfo().title);
|
||||
channel.getManager().setTopic(":speaker: Now playing: " + track.getInfo().title).queueAfter(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessageToChannel(String msg) {
|
||||
if (channel != null) {
|
||||
channel.sendMessage(msg).queue();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEnabled() {
|
||||
return "1".equals(GuildManager.getManager(guild).getSetting(GuildManager.Settings.MUSIC_TOPIC));
|
||||
// rate limiting too much
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -55,16 +55,21 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
|
||||
@Override
|
||||
public void onTrackStart(AudioPlayer player, AudioTrack track) {
|
||||
logger.debug("Starting track on guild {}: {}", guild.getId(), track.getIdentifier());
|
||||
logger.debug("Guild {}: starting track: {}", guild.getId(), track.getIdentifier());
|
||||
topicManager.updateTopic(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
|
||||
logger.debug("Guild {}: currently playing track ended: {}", guild.getId(), track.getIdentifier());
|
||||
|
||||
if (endReason == AudioTrackEndReason.LOAD_FAILED) {
|
||||
logger.debug("Guild {}: failed loading track: {}", guild.getId(), track.getIdentifier());
|
||||
}
|
||||
|
||||
// check if mayStartNext
|
||||
if (endReason == AudioTrackEndReason.FINISHED || endReason == AudioTrackEndReason.LOAD_FAILED) {
|
||||
queueManager.nextTrack(player);
|
||||
|
||||
}
|
||||
|
||||
if (endReason == AudioTrackEndReason.STOPPED) {
|
||||
@@ -84,13 +89,16 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
|
||||
@Override
|
||||
public void onTrackException(AudioPlayer player, AudioTrack track, FriendlyException exception) {
|
||||
logger.debug("Guild {}: exception while playing track [{}]: {}", guild.getId(), track.getIdentifier(), exception.getMessage());
|
||||
topicManager.updateTopic(null);
|
||||
topicManager.getTextChannel().sendMessage("Error while playing track: " + track.getInfo().title).queue();
|
||||
topicManager.sendMessageToChannel("Error while playing track [" + track.getInfo().title + "]: " + exception.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackStuck(AudioPlayer player, AudioTrack track, long thresholdMs) {
|
||||
logger.debug("Guild {}: currently playing track is stuck: {}", guild.getId(), track.getIdentifier());
|
||||
topicManager.updateTopic(null);
|
||||
topicManager.sendMessageToChannel("Current track is stuck, skipping to next");
|
||||
queueManager.nextTrack(player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package netneutrality.music.loadable;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AppleMostPlayed implements LoadableMusicSource {
|
||||
@Override
|
||||
public String url() {
|
||||
return "https://rss.applemarketingtools.com/api/v2/ca/music/most-played/25/songs.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LoadableSong> parse(JSONObject obj) {
|
||||
List<LoadableSong> songs = new ArrayList<>();
|
||||
JSONArray results = obj.getJSONObject("feed").getJSONArray("results");
|
||||
|
||||
results.forEach(o -> {
|
||||
JSONObject song = (JSONObject) o;
|
||||
String artist = song.getString("artistName");
|
||||
String songName = song.getString("name");
|
||||
String artwork = song.getString("artworkUrl100");
|
||||
|
||||
songs.add(new LoadableSong(artist, songName, artwork));
|
||||
});
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "apple";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package netneutrality.music.loadable;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public class CachedSource {
|
||||
private final LoadableMusicSource source;
|
||||
private OffsetDateTime lastAccess;
|
||||
private final List<LoadableSong> songs;
|
||||
|
||||
public CachedSource(LoadableMusicSource source, List<LoadableSong> songs) {
|
||||
this.source = source;
|
||||
this.lastAccess = OffsetDateTime.now();
|
||||
this.songs = songs;
|
||||
}
|
||||
|
||||
public List<LoadableSong> getSongs() {
|
||||
return songs;
|
||||
}
|
||||
|
||||
public OffsetDateTime getLastAccess() {
|
||||
return lastAccess;
|
||||
}
|
||||
|
||||
public LoadableMusicSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public void updateAccessTime() {
|
||||
this.lastAccess = OffsetDateTime.now();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package netneutrality.music.loadable;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface LoadableMusicSource {
|
||||
String url();
|
||||
|
||||
List<LoadableSong> parse(JSONObject obj);
|
||||
|
||||
String getIdentifier();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package netneutrality.music.loadable;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
public record LoadableSong(String artist, String name, String artworkUrl) {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoadableSong{" +
|
||||
"artist='" + artist + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", artworkUrl='" + artworkUrl + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package netneutrality.music.loadable;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
import netneutrality.http.WebModule;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class LoadableSourceManager {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(LoadableSourceManager.class);
|
||||
private static final Map<String, CachedSource> cache = new HashMap<>();
|
||||
|
||||
public CachedSource get(LoadableMusicSource source) {
|
||||
|
||||
if (cache.containsKey(source.getIdentifier())) {
|
||||
CachedSource cachedSource = cache.get(source.getIdentifier());
|
||||
|
||||
if (OffsetDateTime.now().isAfter(cachedSource.getLastAccess().plusHours(4))) {
|
||||
cachedSource.getSongs().clear();
|
||||
cachedSource.getSongs().addAll(loadFromUrl(source));
|
||||
cachedSource.updateAccessTime();
|
||||
}
|
||||
|
||||
return cachedSource;
|
||||
} else {
|
||||
List<LoadableSong> songs = loadFromUrl(source);
|
||||
CachedSource newCachedSource = new CachedSource(source, songs);
|
||||
|
||||
cache.put(source.getIdentifier(), newCachedSource);
|
||||
return newCachedSource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<LoadableSong> loadFromUrl(LoadableMusicSource source) {
|
||||
WebModule web = new WebModule(source.url());
|
||||
JSONObject obj = web.request().getAsObject();
|
||||
|
||||
if (obj == null)
|
||||
return Collections.emptyList();
|
||||
|
||||
List<LoadableSong> songs = source.parse(obj);
|
||||
Collections.shuffle(songs);
|
||||
|
||||
return songs;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
||||
import netneutrality.NetNeutrality;
|
||||
import netneutrality.music.MusicManager;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -29,8 +30,10 @@ public class MusicPlayerAutoDisconnectThread implements Runnable {
|
||||
if (channel != null) {
|
||||
List<Member> members = channel.getMembers().stream().filter(member -> !member.getId().equals(NetNeutrality.getSelf().getId())).toList();
|
||||
|
||||
if (members.size() == 0 || manager.getScheduler().getQueueManager().getQueue().isEmpty())
|
||||
if (members.size() == 0 || manager.getScheduler().getQueueManager().getQueue().isEmpty()) {
|
||||
LoggerFactory.getLogger(MusicPlayerAutoDisconnectThread.class).debug("Guild {}: auto-disconnect player from voice channel: {}", guild.getId(), channel.getId());
|
||||
manager.leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ package netneutrality.utils;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import netneutrality.command.AbstractCommand;
|
||||
@@ -69,7 +70,6 @@ public class MessageFunction {
|
||||
message.setTitle("Currently playing:");
|
||||
message.setColor(Color.BLUE);
|
||||
message.addField("Track title: ", current.getInfo().title, false);
|
||||
message.addField("Uploaded by: ", current.getInfo().author, false);
|
||||
message.addField("Duration: ", DurationFormatUtils.formatDuration(current.getPosition(), "**HH:mm:ss**", true) + " / " + DurationFormatUtils.formatDuration(current.getDuration(), "**HH:mm:ss**", true), false);
|
||||
message.setFooter("Requested by " + requester.getEffectiveName(), requester.getAvatarUrl());
|
||||
message.setTimestamp(OffsetDateTime.now());
|
||||
@@ -84,7 +84,6 @@ public class MessageFunction {
|
||||
message.setTitle("Adding track to queue..");
|
||||
message.setColor(Color.BLUE);
|
||||
message.addField("Track title: ", track.getInfo().title, false);
|
||||
message.addField("Uploaded by: ", track.getInfo().author, false);
|
||||
message.addField("Duration: ", DurationFormatUtils.formatDuration(track.getDuration(), "**HH:mm:ss**", true), false);
|
||||
message.setFooter("Requested by " + user.getEffectiveName(), user.getAvatarUrl());
|
||||
message.setTimestamp(OffsetDateTime.now());
|
||||
@@ -111,15 +110,17 @@ public class MessageFunction {
|
||||
AudioTrack current = manager.getCurrentlyPlaying();
|
||||
|
||||
EmbedBuilder message = new EmbedBuilder();
|
||||
message.setTitle("Current queue (showing max 10 items):");
|
||||
message.setTitle("Current queue (showing 10 out of " + tracks.size() + " items):");
|
||||
message.setColor(Color.BLUE);
|
||||
|
||||
int index = 0;
|
||||
for (AudioTrack track : tracks) {
|
||||
if (track.getInfo().title.equals(current.getInfo().title) && currentlyPlaying) {
|
||||
message.addField("Track #" + ++index + " (Currently playing)", track.getInfo().title, false);
|
||||
AudioTrackInfo info = track.getInfo();
|
||||
|
||||
if (current != null && current.getInfo().title.equals(info.title) && currentlyPlaying) {
|
||||
message.addField("Track #" + ++index + " (Currently playing)", info.title, false);
|
||||
} else {
|
||||
message.addField("Track #" + ++index, track.getInfo().title, false);
|
||||
message.addField("Track #" + ++index, info.title, false);
|
||||
}
|
||||
|
||||
if (index == 10) break;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class MusicUtils {
|
||||
if (UserFunction.isAdmin(context.getGuildUser()) || manager.getRequesterOfCurrentTrack().getId().equals(context.getGuildUser().getId())) {
|
||||
return true;
|
||||
} else {
|
||||
context.reply("You are not powerful enough, scrub");
|
||||
context.reply("You're not powerful enough, scrub");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user