Add voteskip command and update music player
This commit is contained in:
1 parent
dbf6fd549c
commit
048b645e61
41 files changed
+779
-308
No files matched your search
@@ -10,8 +10,6 @@ import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import netneutrality.db.DBController;
|
||||
import netneutrality.db.controllers.DBMessage;
|
||||
import netneutrality.db.entities.OGuild;
|
||||
import netneutrality.handler.ratelimiter.IMessageRateLimiter;
|
||||
import netneutrality.handler.ratelimiter.MessageRateLimiterImpl;
|
||||
@@ -24,17 +22,30 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class GuildManager {
|
||||
|
||||
public enum GuildSettings {
|
||||
MUSIC_ROLE("muisc.role"), MUSIC_CHANNEL("music.channel"), BLACKLIST_CHANNELS("blacklist.exclude.channels");
|
||||
public enum GuildSetting {
|
||||
MUSIC_ROLE("music.role", null), MUSIC_CHANNEL("music.channel", null), BLACKLIST_CHANNELS("blacklist.exclude.channels", null);
|
||||
|
||||
private final String setting;
|
||||
private final String defaultValue;
|
||||
|
||||
GuildSettings(String setting) {
|
||||
GuildSetting(String setting, String defaultValue) {
|
||||
this.setting = setting;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public String getSetting() {
|
||||
return setting;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (setting == null)
|
||||
return defaultValue;
|
||||
|
||||
return setting;
|
||||
}
|
||||
}
|
||||
@@ -61,6 +72,36 @@ public class GuildManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static GuildManager getManager(String guildId) {
|
||||
return managers.getOrDefault(guildId, null);
|
||||
}
|
||||
|
||||
public static Map<String, GuildManager> getManagers() {
|
||||
return managers;
|
||||
}
|
||||
|
||||
public static boolean reloadSettingsForGuild(String guildId) {
|
||||
if (managers.containsKey(guildId)) {
|
||||
GuildManager manager = managers.get(guildId);
|
||||
manager.reloadSettings();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean reloadSettingsForGuild(Guild guild) {
|
||||
if (managers.containsKey(guild.getId())) {
|
||||
GuildManager manager = GuildManager.getManager(guild.getId());
|
||||
manager.reloadSettings();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void checkAndLogMessage(Message message, Member member, TextChannel channel) {
|
||||
//((DBMessage) DBController.get("message")).log(guild, channel, member, message);
|
||||
}
|
||||
@@ -74,10 +115,14 @@ public class GuildManager {
|
||||
return guildEntity.getSettings().getSettingByKey(key);
|
||||
}
|
||||
|
||||
public String getSetting(GuildSettings key) {
|
||||
public String getSetting(GuildSetting key) {
|
||||
return guildEntity.getSettings().getSettingByKey(key.toString());
|
||||
}
|
||||
|
||||
public Map<String, String> getSettings() {
|
||||
return guildEntity.getSettings().getSettings();
|
||||
}
|
||||
|
||||
public void reloadSettings() {
|
||||
guildEntity.reloadSettings();
|
||||
}
|
||||
|
||||
@@ -7,16 +7,15 @@ import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
|
||||
import netneutrality.command.CommandManager;
|
||||
import netneutrality.db.DBController;
|
||||
import netneutrality.handler.EditHandler;
|
||||
import netneutrality.handler.MessageReceivedHandler;
|
||||
import netneutrality.handler.message.EditHandler;
|
||||
import netneutrality.handler.message.MessageReceivedHandler;
|
||||
import netneutrality.handler.ServerJoinHandler;
|
||||
import netneutrality.http.server.WebApi;
|
||||
import netneutrality.music.MusicManager;
|
||||
import netneutrality.thread.BaseThreadFactory;
|
||||
import netneutrality.thread.ShutdownThread;
|
||||
import netneutrality.utils.Settings;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -33,28 +32,20 @@ public class MusicBot {
|
||||
initJDA();
|
||||
|
||||
CommandManager.init();
|
||||
MusicManager.registerSources();
|
||||
jda.getPresence().setActivity(Activity.watching("me load..."));
|
||||
jda.addEventListener(new MessageReceivedHandler(), new EditHandler(), new ServerJoinHandler());
|
||||
|
||||
new WebApi();
|
||||
jda.getPresence().setActivity(Activity.watching("you"));
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
if( LogManager.getContext() instanceof LoggerContext) {
|
||||
logger.debug("Shutting down log4j2");
|
||||
Configurator.shutdown((LoggerContext)LogManager.getContext());
|
||||
}
|
||||
|
||||
MusicBot.shutdown();
|
||||
}));
|
||||
Runtime.getRuntime().addShutdownHook(new BaseThreadFactory("shutdown").newThread(new ShutdownThread()));
|
||||
|
||||
}
|
||||
|
||||
public static void initJDA() {
|
||||
try {
|
||||
jda = JDABuilder.createDefault(Settings.getInstance().get("BOT_TOKEN"))
|
||||
.enableIntents(GatewayIntent.GUILD_MEMBERS, GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.GUILD_VOICE_STATES)
|
||||
.build();
|
||||
jda = JDABuilder.createDefault(Settings.getInstance().get("BOT_TOKEN")).enableIntents(GatewayIntent.GUILD_MEMBERS, GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.GUILD_VOICE_STATES).build();
|
||||
jda.awaitReady();
|
||||
} catch (LoginException | IllegalArgumentException | InterruptedException e) {
|
||||
logger.error(e.getMessage());
|
||||
@@ -77,7 +68,7 @@ public class MusicBot {
|
||||
|
||||
private static void disconnect() {
|
||||
if (jda != null) {
|
||||
jda.shutdownNow();
|
||||
jda.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package netneutrality;
|
||||
|
||||
import netneutrality.thread.BaseThread;
|
||||
import netneutrality.thread.BaseThreadFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -17,7 +17,7 @@ public class ThreadManager {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ThreadManager.class);
|
||||
|
||||
public static ExecutorService getExecutor(String name) {
|
||||
return executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThread(name)));
|
||||
return executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThreadFactory(name)));
|
||||
|
||||
}
|
||||
|
||||
@@ -26,36 +26,18 @@ public class ThreadManager {
|
||||
|
||||
switch (type) {
|
||||
case FIXED:
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newFixedThreadPool(5, new BaseThread(name)));
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new BaseThreadFactory(name)));
|
||||
break;
|
||||
case SCHEDULED:
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newScheduledThreadPool(5, new BaseThread(name)));
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new BaseThreadFactory(name)));
|
||||
break;
|
||||
default:
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThread(name)));
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThreadFactory(name)));
|
||||
}
|
||||
|
||||
return executor;
|
||||
}
|
||||
|
||||
public static ExecutorService getExecutor(String name, ExecutorType type, Integer poolSize) {
|
||||
ExecutorService executor;
|
||||
|
||||
switch (type) {
|
||||
case FIXED:
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newFixedThreadPool(poolSize, new BaseThread(name)));
|
||||
break;
|
||||
case SCHEDULED:
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newScheduledThreadPool(poolSize, new BaseThread(name)));
|
||||
break;
|
||||
default:
|
||||
executor = executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThread(name)));
|
||||
}
|
||||
|
||||
return executor;
|
||||
}
|
||||
|
||||
|
||||
public static Future<?> dispatch(ExecutorService executor, Runnable task) {
|
||||
return executor.submit(task);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package netneutrality.command;/*
|
||||
package netneutrality.command;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
@@ -10,6 +11,8 @@ import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import netneutrality.GuildManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractMusicCommand extends AbstractCommand {
|
||||
|
||||
@Override
|
||||
@@ -24,14 +27,15 @@ public abstract class AbstractMusicCommand extends AbstractCommand {
|
||||
|
||||
@Override
|
||||
public boolean canBeExecutedBy(Guild guild, Member member) {
|
||||
String roleDb = GuildManager.getManager(guild).getSetting(GuildManager.GuildSettings.MUSIC_ROLE);
|
||||
String roleDb = GuildManager.getManager(guild).getSetting(GuildManager.GuildSetting.MUSIC_ROLE);
|
||||
boolean can = true;
|
||||
//System.out.println(roleDb);
|
||||
|
||||
if (roleDb != null && !roleDb.isEmpty()) {
|
||||
Role neededRole = guild.getRoleById(roleDb);
|
||||
return member.getRoles().contains(neededRole);
|
||||
can = member.getRoles().contains(neededRole);
|
||||
}
|
||||
|
||||
return true;
|
||||
return can;
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,12 @@ import netneutrality.utils.Settings;
|
||||
import netneutrality.utils.UserFunction;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public class CommandContext {
|
||||
|
||||
private static final ExecutorService commandExecutor = ThreadManager.getExecutor("command-execution", ThreadManager.ExecutorType.FIXED, 10);
|
||||
private static final ExecutorService commandExecutor = ThreadManager.getExecutor("command-execution", ThreadManager.ExecutorType.FIXED);
|
||||
|
||||
private AbstractCommand command;
|
||||
private final Message message;
|
||||
@@ -49,11 +50,15 @@ public class CommandContext {
|
||||
return new CommandContext(message, member, user, guild, channel, jda);
|
||||
}
|
||||
|
||||
public String getArg(int index) {
|
||||
return getArgumentsAsArray()[index];
|
||||
}
|
||||
|
||||
public String[] getArgumentsAsArray() {
|
||||
String msg = message.getContentDisplay().trim();
|
||||
msg = msg.substring(Settings.getInstance().get("BOT_PREFIX", "$").length()).trim();
|
||||
String cmd = msg.split(" ", 2)[0];
|
||||
String[] args = msg.replaceFirst("(" + cmd + ")(\s)?", "").split("\s");
|
||||
String[] args = msg.replaceFirst("(" + cmd + ")(\\s+)?", "").split("\s");
|
||||
|
||||
if (args.length == 1 && args[0].isEmpty())
|
||||
args = new String[0];
|
||||
@@ -97,6 +102,42 @@ public class CommandContext {
|
||||
return command;
|
||||
}
|
||||
|
||||
public void reply(String msg) {
|
||||
if (channel != null) {
|
||||
channel.sendMessage(msg).queue();
|
||||
}
|
||||
}
|
||||
|
||||
public void reply(Message msg) {
|
||||
if (channel != null) {
|
||||
channel.sendMessage(msg).queue();
|
||||
}
|
||||
}
|
||||
|
||||
public void reply(MessageEmbed embed, MessageEmbed... embeds) {
|
||||
if (channel != null) {
|
||||
channel.sendMessageEmbeds(embed, embeds).queue();
|
||||
}
|
||||
}
|
||||
|
||||
public void reply(Collection<? extends MessageEmbed> embeds) {
|
||||
if (channel != null) {
|
||||
channel.sendMessageEmbeds(embeds).queue();
|
||||
}
|
||||
}
|
||||
|
||||
public void replyPrivate(String msg) {
|
||||
user.openPrivateChannel().flatMap(channel -> channel.sendMessage(msg)).queue();
|
||||
}
|
||||
|
||||
public void replyPrivate(Message msg) {
|
||||
user.openPrivateChannel().flatMap(channel -> channel.sendMessage(msg)).queue();
|
||||
}
|
||||
|
||||
public void replyPrivate(Collection<? extends MessageEmbed> embeds) {
|
||||
user.openPrivateChannel().flatMap(channel -> channel.sendMessageEmbeds(embeds)).queue();
|
||||
}
|
||||
|
||||
public void dispatch(AbstractCommand command) {
|
||||
this.command = command;
|
||||
//TODO: Add usage check
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package netneutrality.command;/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class CommandUsage {
|
||||
|
||||
public static class Argument {
|
||||
public enum Type {
|
||||
OPTIONAL, REQUIRED
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
private final String description;
|
||||
|
||||
public Argument(Type t, String desc) {
|
||||
this.type = t;
|
||||
this.description = desc;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<Argument> args = new HashSet<>();
|
||||
|
||||
public CommandUsage(Argument... arguments) {
|
||||
Collections.addAll(args, arguments);
|
||||
}
|
||||
|
||||
public static CommandUsage create(Argument... arguments) {
|
||||
return new CommandUsage(arguments);
|
||||
}
|
||||
|
||||
public Set<Argument> getArguments() {
|
||||
return args;
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ public class HelpCommand extends AbstractCommand {
|
||||
public void execute(CommandContext context) {
|
||||
List<MessageEmbed> help = MessageFunction.buildHelpMessage(CommandManager.commands, CommandManager.commandsAlias, UserFunction.isAdmin(context.getGuildUser()));
|
||||
|
||||
context.getChannel().sendMessage(new MessageBuilder().append(context.getDiscordUser()).append(" help has been sent your way!").build()).queue();
|
||||
context.getDiscordUser().openPrivateChannel().queue(t -> t.sendMessageEmbeds(help).queue());
|
||||
context.reply(new MessageBuilder().append(context.getDiscordUser()).append(" help has been sent your way!").build());
|
||||
context.replyPrivate(help);
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class PingCommand extends AbstractCommand {
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
if (context.getArgumentsAsArray().length == 0)
|
||||
context.getChannel().sendMessage("Pong! [" + MusicBot.getJDA().getGatewayPing() + " ms]").queue();
|
||||
context.reply(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class BitcoinPriceCommand extends AbstractCommand {
|
||||
throw new CommandExecutionException("Error during web request", context, e);
|
||||
}
|
||||
|
||||
t.editMessage(String.format("The current price of %s in %s is %s$", crypto, finalCurrency, price)).queue();
|
||||
t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class CryptoPriceCommand extends AbstractCommand {
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<crypto> <currency>";
|
||||
return "<crypto> <currency (optional)>";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -88,7 +88,7 @@ public class EthereumPriceCommand extends AbstractCommand {
|
||||
throw new CommandExecutionException("Error during web request", context, e);
|
||||
}
|
||||
|
||||
t.editMessage(String.format("The current price of %s in %s is %s$", crypto, finalCurrency, price)).queue();
|
||||
t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public class LitecoinPriceCommand extends AbstractCommand {
|
||||
throw new CommandExecutionException("Error during web request", context, e);
|
||||
}
|
||||
|
||||
t.editMessage(String.format("The current price of %s in %s is %s$", crypto, finalCurrency, price)).queue();
|
||||
t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
return "Deletes the music queue";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,7 +37,7 @@ public class JoinCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
return "Make the bot join the current voice channel (if no music is playing, bot will disconnect automatically)";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,7 +40,7 @@ public class LeaveCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
return "Make the bot leave the voice channel";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,19 +35,19 @@ public class PlayCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Get the party going";
|
||||
return "Get the party going!";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
MusicManager player = MusicManager.get(context.getGuild());
|
||||
context.getMessage().delete().queue();
|
||||
|
||||
if (context.getArgumentsAsArray().length > 0) {
|
||||
context.getMessage().delete().queue();
|
||||
player.play(context.getMessageText(), context, false, false);
|
||||
|
||||
} else {
|
||||
context.getChannel().sendMessage("No url provided").queue();
|
||||
context.reply("No url provided");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,12 +35,12 @@ public class SkipCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return null;
|
||||
return "<number of track to skip (optional)>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
return "Used to skip to the next track in the queue (requires admin privileges)";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,6 +48,12 @@ public class SkipCommand extends AbstractMusicCommand {
|
||||
MusicManager player = MusicManager.get(context.getGuild());
|
||||
MusicUtils.checkIfConnected(player, context);
|
||||
|
||||
player.skip();
|
||||
if (context.getArgumentsAsArray().length > 0) {
|
||||
int skips = Integer.parseInt(context.getArg(0));
|
||||
player.skip(skips);
|
||||
} else {
|
||||
player.skip(1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,9 @@ import netneutrality.command.AbstractMusicCommand;
|
||||
import netneutrality.command.CommandContext;
|
||||
import netneutrality.music.MusicManager;
|
||||
import netneutrality.utils.MusicUtils;
|
||||
import netneutrality.utils.UserFunction;
|
||||
|
||||
public class StopCommand extends AbstractMusicCommand {
|
||||
@Override
|
||||
public boolean needAdmin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
@@ -40,7 +37,7 @@ public class StopCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
return "Stop the music player, deleting the queue in the process";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,6 +45,13 @@ public class StopCommand extends AbstractMusicCommand {
|
||||
MusicManager player = MusicManager.get(context.getGuild());
|
||||
MusicUtils.checkIfConnected(player, context);
|
||||
|
||||
player.leave();
|
||||
if (UserFunction.isAdmin(context.getGuildUser())) {
|
||||
player.leave();
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.getGuildUser().getId().equals(player.getRequesterOfCurrentTrack().getId())) {
|
||||
player.leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class ViewQueueCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String[] getAlias() {
|
||||
return new String[]{"viewq"};
|
||||
return new String[]{"viewq", "queue"};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,7 +42,7 @@ public class ViewQueueCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
return "Get the current queue for the music player";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,9 +53,9 @@ public class ViewQueueCommand extends AbstractMusicCommand {
|
||||
|
||||
int queueSize = player.getScheduler().getQueue().size();
|
||||
if (queueSize > 0) {
|
||||
context.getChannel().sendMessageEmbeds(MessageFunction.buildViewQueueMessage(player, member)).queue();
|
||||
context.reply(MessageFunction.buildViewQueueMessage(player, member));
|
||||
} else {
|
||||
context.getChannel().sendMessage("Queue is empty!").queue();
|
||||
context.reply("Queue is empty!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ package netneutrality.command.music;
|
||||
|
||||
import netneutrality.command.AbstractMusicCommand;
|
||||
import netneutrality.command.CommandContext;
|
||||
import netneutrality.command.CommandUsage;
|
||||
import netneutrality.exceptions.CommandErrorException;
|
||||
import netneutrality.music.MusicManager;
|
||||
import netneutrality.utils.MusicUtils;
|
||||
@@ -31,17 +32,17 @@ public class VolumeCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String[] getAlias() {
|
||||
return new String[0];
|
||||
return new String[] { "vol" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return null;
|
||||
return "<integer between 0 and 100 (optional)>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
return "Sets the volume for the music player";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,17 +8,19 @@ package netneutrality.command.music;
|
||||
|
||||
import netneutrality.command.AbstractMusicCommand;
|
||||
import netneutrality.command.CommandContext;
|
||||
import netneutrality.music.MusicManager;
|
||||
import netneutrality.utils.MusicUtils;
|
||||
|
||||
public class VoteSkipCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommand() {
|
||||
return null;
|
||||
return "voteskip";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -33,11 +35,14 @@ public class VoteSkipCommand extends AbstractMusicCommand {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return null;
|
||||
return "Cast a vote to skip the currently playing track";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
MusicUtils.checkIfConnected(manager, context);
|
||||
|
||||
manager.voteSkip(context);
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public class DBController {
|
||||
if (controllers.isEmpty())
|
||||
loadControllers();
|
||||
|
||||
((ScheduledExecutorService) ThreadManager.getExecutor("db-keepalive", ThreadManager.ExecutorType.SCHEDULED, 5)).scheduleWithFixedDelay(() -> {
|
||||
((ScheduledExecutorService) ThreadManager.getExecutor("db-keepalive", ThreadManager.ExecutorType.SCHEDULED)).scheduleWithFixedDelay(() -> {
|
||||
DBController.get().query("SELECT 1;");
|
||||
}, 0, 120, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ public class DBBlacklist extends AbstractController {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void delete(String word, String serverId, Consumer<Boolean> success) {
|
||||
isAlreadyBlacklisted(word, serverId, blacklisted -> {
|
||||
if (blacklisted >= 1) {
|
||||
@@ -119,18 +121,13 @@ public class DBBlacklist extends AbstractController {
|
||||
return output;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private boolean isAlreadyBlacklisted(String word, String serverId) {
|
||||
AtomicBoolean result = new AtomicBoolean();
|
||||
MTableModel table = database.prepareAndExecuteAsync("SELECT COUNT(*) FROM blacklist WHERE word = ? AND guild_id = ?", word, serverId).blocking();
|
||||
if (!table.isEmpty()) {
|
||||
return ((int) table.getRowModel(0).getItem(0)) != 0;
|
||||
}
|
||||
|
||||
database.prepareAndExecuteAsync("SELECT COUNT(*) FROM blacklist WHERE word = ? AND guild_id = ?", word, serverId).async(table -> {
|
||||
if (!table.isEmpty()) {
|
||||
result.set((int) table.getRowModel(0).getItem(0) != 0);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return result.get();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void isAlreadyBlacklisted(String word, String serverId, Consumer<Integer> result) {
|
||||
|
||||
@@ -30,13 +30,13 @@ public abstract class AbstractEntity implements EntityInterface {
|
||||
for (String pk : getPrimaryKeys()) {
|
||||
whereClause.append(pk + " = ?");
|
||||
|
||||
//TODO: Fix last and
|
||||
if (getPrimaryKeys().length > 1)
|
||||
whereClause.append(" AND ");
|
||||
}
|
||||
|
||||
|
||||
String sql = "SELECT * FROM " + getTableName() + " WHERE " + whereClause;
|
||||
MusicBot.logger.debug(sql + " - pk: " + primaryKey);
|
||||
// MusicBot.logger.debug(sql + " - pk: " + primaryKey);
|
||||
|
||||
if (this.primaryKeys.length > 0)
|
||||
this.table = DBController.get().prepareAndExecuteAsync(sql, this.primaryKey, this.primaryKeys).blocking();
|
||||
|
||||
@@ -32,14 +32,34 @@ public class MRowModel {
|
||||
return rowIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the row. No checks are made to match the table itself
|
||||
* @param obj Object to add to the row
|
||||
*/
|
||||
public void addColumnToRow(Object obj) {
|
||||
row.add(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all objects in the row.
|
||||
* @return List of objects
|
||||
*/
|
||||
public List<Object> getRow() {
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Get an item at the specified index.
|
||||
*
|
||||
* Example:
|
||||
* SQL: SELECT first, second, third
|
||||
* Index: 0 1 2
|
||||
* </pre>
|
||||
*
|
||||
* @param index Index
|
||||
* @return The object
|
||||
*/
|
||||
public Object getItem(int index) {
|
||||
try {
|
||||
return row.get(index);
|
||||
|
||||
@@ -67,6 +67,12 @@ public class MTableModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent a row in a table
|
||||
*
|
||||
* @param rowIndex The index of the row
|
||||
* @return A row model
|
||||
*/
|
||||
public MRowModel getRowModel(int rowIndex) {
|
||||
if (getNbRows() != 0)
|
||||
return rows.getRowModel(rowIndex);
|
||||
|
||||
@@ -45,6 +45,6 @@ public class LogHandler {
|
||||
|
||||
private static void sendMessageToChannel(CommandErrorException error) {
|
||||
CommandContext context = error.getCommandContext();
|
||||
context.getChannel().sendMessage(error.getMessage()).queue();
|
||||
context.reply(error.getMessage());
|
||||
}
|
||||
}
|
||||
+10
-7
@@ -1,4 +1,4 @@
|
||||
package netneutrality.handler;
|
||||
package netneutrality.handler.message;
|
||||
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
@@ -25,10 +25,12 @@ public class EditHandler extends ListenerAdapter {
|
||||
|
||||
if (event.getAuthor().isBot()) return;
|
||||
|
||||
MTableModel table = DBController.get().prepareAndExecuteAsync("SELECT channel_id FROM logging WHERE guild_id = ? AND enabled = 1", event.getGuild().getId()).blocking();
|
||||
MTableModel table = DBController.get().prepareAndExecuteAsync("SELECT channel_id, guild_id FROM logging WHERE guild_id = ? AND enabled = 1", event.getGuild().getId()).blocking();
|
||||
|
||||
Object logChannel = table.getRowModel(0).getItem(0);
|
||||
if (logChannel != null) {
|
||||
Object guild = table.getRowModel(0).getItem(1);
|
||||
|
||||
if (logChannel != null && guild != null) {
|
||||
String originalMessage = ((DBMessage) DBController.get("message")).getMessageString(event.getMessage().getId());
|
||||
((DBMessage) DBController.get("message")).logEdit(event.getMessage().getId(), event.getMessage().getContentDisplay());
|
||||
|
||||
@@ -38,18 +40,19 @@ public class EditHandler extends ListenerAdapter {
|
||||
try {
|
||||
editEmbed.addField("Original message", (originalMessage == null ? "Not available" : originalMessage), false);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
editEmbed.addField("Original message :", "Message too long. Check db for full message", false);
|
||||
editEmbed.addField("Original message:", "Message too long.", false);
|
||||
}
|
||||
|
||||
try {
|
||||
editEmbed.addField("Edited to :", event.getMessage().getContentDisplay(), false);
|
||||
editEmbed.addField("Edited to:", event.getMessage().getContentDisplay(), false);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
editEmbed.addField("Edited to :", "Message too long. Check db for full message", false);
|
||||
editEmbed.addField("Edited to:", "Message too long.", false);
|
||||
}
|
||||
|
||||
editEmbed.setFooter("ID : " + event.getMessageId(), null);
|
||||
editEmbed.setTimestamp(event.getMessage().getTimeCreated());
|
||||
event.getJDA().getTextChannelById(logChannel.toString()).sendMessageEmbeds(editEmbed.build()).queue();
|
||||
|
||||
event.getJDA().getGuildById((String) guild).getTextChannelById((String) logChannel).sendMessageEmbeds(editEmbed.build()).queue();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package netneutrality.handler;
|
||||
package netneutrality.handler.message;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
@@ -7,6 +7,7 @@ package netneutrality.handler;
|
||||
*/
|
||||
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent;
|
||||
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import netneutrality.GuildManager;
|
||||
@@ -51,5 +52,4 @@ public class MessageReceivedHandler extends ListenerAdapter {
|
||||
GuildManager.getManager(guild).checkBlacklist(message, member, channel);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,13 +6,13 @@ package netneutrality.http.server;/*
|
||||
*/
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import netneutrality.GuildManager;
|
||||
import netneutrality.MusicBot;
|
||||
import netneutrality.http.WebModule;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@@ -25,6 +25,8 @@ public class ActionHandler extends AbstractHandler {
|
||||
if (path.equals("/actions/shutdown")) {
|
||||
LogManager.getLogger(MusicBot.class).info("Request to shutdown received");
|
||||
sendStringResponse(exchange, "Shutting down..");
|
||||
MusicBot.shutdown();
|
||||
|
||||
System.exit(0);
|
||||
return;
|
||||
}
|
||||
@@ -38,6 +40,37 @@ public class ActionHandler extends AbstractHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.startsWith("/actions/settings/current/")) {
|
||||
JSONObject json = new JSONObject();
|
||||
String[] args = exchange.getRequestURI().toString().split("/");
|
||||
String guild = args[args.length - 1];
|
||||
|
||||
GuildManager manager = GuildManager.getManager(MusicBot.getJDA().getGuildById(guild));
|
||||
if (manager != null) {
|
||||
Map<String, String> settings = manager.getSettings();
|
||||
JSONObject setting = new JSONObject(settings);
|
||||
|
||||
json.put("status", "ok");
|
||||
json.put("settings", setting);
|
||||
} else {
|
||||
json.put("status", "error");
|
||||
}
|
||||
|
||||
sendJsonResponse(exchange, json.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.startsWith("/actions/settings/reload/")) {
|
||||
TreeMap<String, String> json = new TreeMap<>();
|
||||
String[] args = exchange.getRequestURI().toString().split("/");
|
||||
String guild = args[args.length - 1];
|
||||
|
||||
json.put("status", String.valueOf(GuildManager.reloadSettingsForGuild(MusicBot.getJDA().getGuildById(guild))));
|
||||
sendJsonResponse(exchange, WebModule.createJson(json));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sendStringResponse(exchange, path);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import netneutrality.MusicBot;
|
||||
import netneutrality.http.WebModule;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -28,15 +30,67 @@ public class GuildHandler extends AbstractHandler {
|
||||
|
||||
if (path.equals("/guilds/owner")) {
|
||||
|
||||
TreeMap<String, String> owners = new TreeMap<>();
|
||||
JSONArray array = new JSONArray();
|
||||
|
||||
JDA jda = MusicBot.getJDA();
|
||||
|
||||
jda.getGuilds().forEach(guild -> {
|
||||
owners.put(guild.getId(), guild.getOwnerId());
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("guild_id", guild.getId());
|
||||
obj.put("owner_id", guild.getOwnerId());
|
||||
array.put(obj);
|
||||
});
|
||||
|
||||
sendJsonResponse(exchange, WebModule.createJsonArray(owners));
|
||||
sendJsonResponse(exchange, array.toString());
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (path.startsWith("/guilds/channels/")) {
|
||||
|
||||
String[] args = exchange.getRequestURI().toString().split("/");
|
||||
String guild = args[args.length - 1];
|
||||
JSONArray array = new JSONArray();
|
||||
|
||||
JDA jda = MusicBot.getJDA();
|
||||
|
||||
if (jda.getGuildById(guild) == null) {
|
||||
sendStringResponse(exchange, path);
|
||||
return;
|
||||
}
|
||||
|
||||
jda.getGuildById(guild).getTextChannels().forEach(channel -> {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("channel_id", channel.getId());
|
||||
obj.put("channel_name", channel.getName());
|
||||
array.put(obj);
|
||||
});
|
||||
|
||||
sendJsonResponse(exchange, array.toString());
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (path.startsWith("/guilds/roles/")) {
|
||||
|
||||
String[] args = exchange.getRequestURI().toString().split("/");
|
||||
String guild = args[args.length - 1];
|
||||
JSONArray array = new JSONArray();
|
||||
JDA jda = MusicBot.getJDA();
|
||||
|
||||
if (jda.getGuildById(guild) == null) {
|
||||
sendStringResponse(exchange, path);
|
||||
return;
|
||||
}
|
||||
|
||||
jda.getGuildById(guild).getRoles().forEach(role -> {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("channel_id", role.getId());
|
||||
obj.put("channel_name", role.getName());
|
||||
array.put(obj);
|
||||
});
|
||||
|
||||
sendJsonResponse(exchange, array.toString());
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ package netneutrality.http.server;
|
||||
*/
|
||||
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import netneutrality.thread.BaseThread;
|
||||
import netneutrality.thread.BaseThreadFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.concurrent.Executors;
|
||||
public class WebApi {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(WebApi.class);
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(10, new BaseThread("web-api"));
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(10, new BaseThreadFactory("web-api"));
|
||||
|
||||
private final int port = 9000;
|
||||
private HttpServer server;
|
||||
|
||||
@@ -24,11 +24,16 @@ public class LoadResultHandler implements AudioLoadResultHandler {
|
||||
private final boolean silent;
|
||||
|
||||
public LoadResultHandler(String identifier, TextChannel channel, Member user, TrackScheduler scheduler, boolean silent) {
|
||||
if (user == null)
|
||||
silent = true;
|
||||
|
||||
this.identifier = identifier;
|
||||
this.channel = channel;
|
||||
this.user = user;
|
||||
this.scheduler = scheduler;
|
||||
this.silent = silent;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,7 +42,7 @@ public class LoadResultHandler implements AudioLoadResultHandler {
|
||||
channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(audioTrack, user, identifier)).queue();
|
||||
}
|
||||
|
||||
scheduler.queue(audioTrack);
|
||||
scheduler.queue(audioTrack, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,12 +51,15 @@ public class LoadResultHandler implements AudioLoadResultHandler {
|
||||
if (identifier.startsWith("ytsearch:")) {
|
||||
AudioTrack track = audioPlaylist.getTracks().get(0);
|
||||
|
||||
channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(track, user, String.format("https://youtu.be/%s", track.getIdentifier()))).queue();
|
||||
scheduler.queue(track);
|
||||
if (!silent)
|
||||
channel.sendMessageEmbeds(MessageFunction.buildAddingTrackMessage(track, user, String.format("https://youtu.be/%s", track.getIdentifier()))).queue();
|
||||
|
||||
scheduler.queue(track, user);
|
||||
} else {
|
||||
channel.sendMessageEmbeds(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, user, identifier)).queue();
|
||||
if (!silent)
|
||||
channel.sendMessageEmbeds(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, user, identifier)).queue();
|
||||
for (AudioTrack track : audioPlaylist.getTracks()) {
|
||||
scheduler.queue(track);
|
||||
scheduler.queue(track, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,9 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -32,8 +33,9 @@ import java.util.concurrent.TimeUnit;
|
||||
public class MusicManager {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(MusicManager.class);
|
||||
private final Guild guild;
|
||||
private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
|
||||
|
||||
private final Guild guild;
|
||||
private final AudioPlayer player;
|
||||
private final TrackScheduler scheduler;
|
||||
private final static Map<String, MusicManager> managers = new ConcurrentHashMap<>();
|
||||
@@ -47,9 +49,6 @@ public class MusicManager {
|
||||
player.addListener(scheduler);
|
||||
player.setVolume(15);
|
||||
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
AudioSourceManagers.registerLocalSource(playerManager);
|
||||
|
||||
managers.put(guild.getId(), this);
|
||||
}
|
||||
|
||||
@@ -61,6 +60,10 @@ public class MusicManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerSources() {
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
}
|
||||
|
||||
public boolean isConnectedTo(VoiceChannel vChannel) {
|
||||
return vChannel != null && vChannel.equals(guild.getAudioManager().getConnectedChannel());
|
||||
}
|
||||
@@ -69,7 +72,7 @@ public class MusicManager {
|
||||
if (vChannel != null && !isConnectedTo(vChannel)) {
|
||||
guild.getAudioManager().openAudioConnection(vChannel);
|
||||
|
||||
((ScheduledExecutorService) ThreadManager.getExecutor("music", ThreadManager.ExecutorType.SCHEDULED, 5)).scheduleWithFixedDelay(() -> {
|
||||
((ScheduledExecutorService) ThreadManager.getExecutor("music", ThreadManager.ExecutorType.SCHEDULED)).scheduleWithFixedDelay(() -> {
|
||||
if ((getCurrentlyPlaying() == null && scheduler.getQueue().isEmpty()) || vChannel.getMembers().size() == 0) {
|
||||
leave();
|
||||
}
|
||||
@@ -84,18 +87,23 @@ public class MusicManager {
|
||||
return guild != null && guild.getAudioManager().getConnectedChannel() != null;
|
||||
}
|
||||
|
||||
public synchronized AudioTrack getCurrentlyPlaying() {
|
||||
public AudioTrack getCurrentlyPlaying() {
|
||||
return player.getPlayingTrack();
|
||||
}
|
||||
|
||||
public synchronized void leave() {
|
||||
public Member getRequesterOfCurrentTrack() {
|
||||
TrackScheduler.TrackInfo info = scheduler.getQueue().peek();
|
||||
return info.getRequester();
|
||||
}
|
||||
|
||||
public void leave() {
|
||||
if (isConnected()) {
|
||||
player.stopTrack();
|
||||
guild.getAudioManager().closeAudioConnection();
|
||||
}
|
||||
|
||||
scheduler.resetTopic();
|
||||
|
||||
System.out.println(scheduler.getQueue().size());
|
||||
}
|
||||
|
||||
public static void disconnectPlayers() {
|
||||
@@ -106,6 +114,12 @@ public class MusicManager {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean restoreQueue(List<String> track) {
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void play(String url, CommandContext context, boolean needToBeConnected, boolean silent) {
|
||||
Member member = context.getGuildUser();
|
||||
TextChannel channel = context.getChannel();
|
||||
@@ -139,15 +153,49 @@ public class MusicManager {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void skip() {
|
||||
public void skip(int nbTrack) {
|
||||
if (!scheduler.getQueue().isEmpty()) {
|
||||
scheduler.nextTrack();
|
||||
if (nbTrack >= scheduler.getQueue().size()) {
|
||||
nbTrack = 1;
|
||||
}
|
||||
|
||||
scheduler.skipAndPlay(nbTrack);
|
||||
} else {
|
||||
leave();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setVolume(int volume) {
|
||||
public void voteSkip(CommandContext context) {
|
||||
Queue<TrackScheduler.TrackInfo> queue = scheduler.getQueue();
|
||||
VoiceChannel voiceChannel = guild.getAudioManager().getConnectedChannel();
|
||||
|
||||
if (getCurrentlyPlaying() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Minus the bot itself
|
||||
int connected = voiceChannel.getMembers().size() - 1;
|
||||
if (connected > 2) {
|
||||
TrackScheduler.TrackInfo info = queue.peek();
|
||||
|
||||
double needed = connected / 2.1;
|
||||
|
||||
if (info != null) {
|
||||
info.toggleSkip(context.getGuildUser());
|
||||
|
||||
if (info.getSkips().size() > needed) {
|
||||
skip(1);
|
||||
} else {
|
||||
context.reply(String.format("Current skips: %d/%f", info.getSkips().size(), Math.ceil(needed)));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
skip(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVolume(int volume) {
|
||||
player.setVolume(volume);
|
||||
}
|
||||
|
||||
@@ -155,14 +203,11 @@ public class MusicManager {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
public ArrayList<String> getAllQueuedTrack() {
|
||||
ArrayList<String> queuedTracks = new ArrayList<>();
|
||||
BlockingQueue<AudioTrack> queue = scheduler.getQueue();
|
||||
public ArrayList<AudioTrack> getAllQueuedTrack() {
|
||||
ArrayList<AudioTrack> tracks = new ArrayList<>();
|
||||
Queue<TrackScheduler.TrackInfo> queue = scheduler.getQueue();
|
||||
|
||||
queue.forEach((a) -> {
|
||||
queuedTracks.add(a.getInfo().title);
|
||||
});
|
||||
|
||||
return queuedTracks;
|
||||
queue.forEach(trackInfo -> tracks.add(trackInfo.getTrack()));
|
||||
return tracks;
|
||||
}
|
||||
}
|
||||
@@ -12,68 +12,131 @@ import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class TrackScheduler extends AudioEventAdapter {
|
||||
|
||||
class TrackInfo {
|
||||
|
||||
private final AudioTrack track;
|
||||
private final Member member;
|
||||
private final Set<String> skips;
|
||||
|
||||
public TrackInfo(AudioTrack track, Member member) {
|
||||
this.track = track;
|
||||
this.member = member;
|
||||
this.skips = new HashSet<>();
|
||||
}
|
||||
|
||||
public AudioTrack getTrack() {
|
||||
return track;
|
||||
}
|
||||
|
||||
public Set<String> getSkips() {
|
||||
return skips;
|
||||
}
|
||||
|
||||
public void toggleSkip(Member member) {
|
||||
if (!hasSkip(member))
|
||||
skips.add(member.getId());
|
||||
else
|
||||
skips.remove(member.getId());
|
||||
}
|
||||
|
||||
public boolean hasSkip(Member member) {
|
||||
return skips.contains(member.getId());
|
||||
}
|
||||
|
||||
public Member getRequester() {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
|
||||
private final Object topicLock = new Object();
|
||||
private final AudioPlayer player;
|
||||
private final Queue<TrackInfo> queue;
|
||||
private TextChannel channel;
|
||||
private final BlockingQueue<AudioTrack> queue;
|
||||
public String topic;
|
||||
private String originalTopic;
|
||||
|
||||
public TrackScheduler(AudioPlayer player) {
|
||||
this.player = player;
|
||||
this.queue = new LinkedBlockingQueue<>();
|
||||
}
|
||||
|
||||
public void queue(AudioTrack track) {
|
||||
public void queue(AudioTrack track, Member member) {
|
||||
// Calling startTrack with the noInterrupt set to true will start the track only if nothing is currently playing. If
|
||||
// something is playing, it returns false and does nothing. In that case the player was already playing so this
|
||||
// track goes to the queue instead.
|
||||
boolean start = player.startTrack(track, true);
|
||||
queue.offer(new TrackInfo(track, member));
|
||||
|
||||
if (!start) {
|
||||
queue.offer(track);
|
||||
if (player.getPlayingTrack() == null) {
|
||||
player.startTrack(track, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextChannel(TextChannel channel) {
|
||||
this.channel = channel;
|
||||
|
||||
if (topic == null) {
|
||||
topic = channel.getTopic();
|
||||
public String getOriginalTopic() {
|
||||
synchronized (topicLock) {
|
||||
return originalTopic;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public TextChannel getTextChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public BlockingQueue<AudioTrack> getQueue() {
|
||||
public void setTextChannel(TextChannel channel) {
|
||||
this.channel = channel;
|
||||
|
||||
synchronized (topicLock) {
|
||||
if (originalTopic == null) {
|
||||
originalTopic = channel.getTopic();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void resetTextChannel() {
|
||||
this.channel = null;
|
||||
}
|
||||
|
||||
public Queue<TrackInfo> getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
public void resetTopic() {
|
||||
if (channel != null && (topic != null && !topic.equals(""))) {
|
||||
//channel.getManager().setTopic(topic).queue();
|
||||
synchronized (topicLock) {
|
||||
if (channel != null && (originalTopic != null && !originalTopic.equals(""))) {
|
||||
//channel.getManager().setTopic(topic).queue();
|
||||
}
|
||||
|
||||
originalTopic = null;
|
||||
}
|
||||
|
||||
topic = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the next track, stopping the current one if it is playing.
|
||||
*/
|
||||
public void nextTrack() {
|
||||
// Start the next track, regardless of if something is already playing or not. In case queue was empty, we are
|
||||
// giving null to startTrack, which is a valid argument and will simply stop the player.
|
||||
AudioTrack track = queue.poll();
|
||||
if (track != null) {
|
||||
player.startTrack(track, false);
|
||||
public void nextTrack(AudioPlayer player) {
|
||||
TrackInfo last = queue.poll();
|
||||
|
||||
if (queue.peek() != null) {
|
||||
player.startTrack(queue.peek().getTrack(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void skipAndPlay(int nb) {
|
||||
if (nb == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < nb; i++) {
|
||||
TrackInfo last = queue.poll();
|
||||
}
|
||||
|
||||
TrackInfo current = queue.peek();
|
||||
if (current != null) {
|
||||
player.startTrack(current.getTrack(), false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -99,7 +162,9 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
resetTopic();
|
||||
|
||||
if (endReason.mayStartNext) {
|
||||
nextTrack();
|
||||
nextTrack(player);
|
||||
} else {
|
||||
queue.poll();
|
||||
}
|
||||
|
||||
// endReason == FINISHED: A track finished or died by an exception (mayStartNext = true).
|
||||
@@ -119,6 +184,6 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
@Override
|
||||
public void onTrackStuck(AudioPlayer player, AudioTrack track, long thresholdMs) {
|
||||
resetTopic();
|
||||
nextTrack();
|
||||
nextTrack(player);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -11,12 +11,12 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class BaseThread implements ThreadFactory {
|
||||
public class BaseThreadFactory implements ThreadFactory {
|
||||
|
||||
private final AtomicLong threadId = new AtomicLong(1);
|
||||
private final String name;
|
||||
|
||||
public BaseThread(String name) {
|
||||
public BaseThreadFactory(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package netneutrality.thread;/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
import netneutrality.MusicBot;
|
||||
import netneutrality.utils.UnsafeShutdown;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
|
||||
public class ShutdownThread implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (LogManager.getContext() instanceof LoggerContext) {
|
||||
System.out.println("Shutting down log4j2");
|
||||
Configurator.shutdown((LoggerContext) LogManager.getContext());
|
||||
}
|
||||
|
||||
MusicBot.shutdown();
|
||||
if (!UnsafeShutdown.SAFE) {
|
||||
//UnsafeShutdown.saveState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ public class ChannelFunction {
|
||||
|
||||
if (toDelete >= 2500) return;
|
||||
|
||||
ThreadManager.getExecutor("bulk-delete", ThreadManager.ExecutorType.FIXED, 5).submit(() -> {
|
||||
ThreadManager.getExecutor("bulk-delete", ThreadManager.ExecutorType.FIXED).submit(() -> {
|
||||
|
||||
int toDeleteFinal = toDelete + 1;
|
||||
int iteration = toDeleteFinal / 100;
|
||||
|
||||
@@ -69,6 +69,7 @@ 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 " + user.getUser().getName(), user.getUser().getAvatarUrl());
|
||||
message.setTimestamp(OffsetDateTime.now());
|
||||
@@ -83,6 +84,7 @@ 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.getUser().getName(), user.getUser().getAvatarUrl());
|
||||
message.setTimestamp(OffsetDateTime.now());
|
||||
@@ -105,17 +107,20 @@ public class MessageFunction {
|
||||
}
|
||||
|
||||
public static MessageEmbed buildViewQueueMessage(MusicManager manager, Member user) {
|
||||
ArrayList<String> tracks = manager.getAllQueuedTrack();
|
||||
ArrayList<AudioTrack> tracks = manager.getAllQueuedTrack();
|
||||
AudioTrack current = manager.getCurrentlyPlaying();
|
||||
|
||||
EmbedBuilder message = new EmbedBuilder();
|
||||
message.setTitle("Current queue (showing max 10 items):");
|
||||
message.setColor(Color.BLUE);
|
||||
message.addField("Track #1 (Currently playing)", current.getInfo().title, false);
|
||||
|
||||
int index = 1;
|
||||
for (String track: tracks) {
|
||||
message.addField("Track #" + ++index, track, false);
|
||||
int index = 0;
|
||||
for (AudioTrack track: tracks) {
|
||||
if (track.getInfo().title.equals(current.getInfo().title)) {
|
||||
message.addField("Track #" + ++index + " (Currently playing)", track.getInfo().title, false);
|
||||
} else {
|
||||
message.addField("Track #" + ++index, track.getInfo().title, false);
|
||||
}
|
||||
|
||||
if (index == 10) break;
|
||||
}
|
||||
@@ -136,8 +141,9 @@ public class MessageFunction {
|
||||
if (command.getType() == null)
|
||||
continue;
|
||||
|
||||
String usage = "None";
|
||||
String usage = "(no arguments required)";
|
||||
String description = "No description yet";
|
||||
StringBuilder availAlias = new StringBuilder();
|
||||
|
||||
if (command.isEnabled() && command.getType() != CommandType.UNLISTED) {
|
||||
if (command.getType() == CommandType.ADMINISTRATION && !admin)
|
||||
@@ -149,6 +155,18 @@ public class MessageFunction {
|
||||
if (command.getDescription() != null)
|
||||
description = command.getDescription();
|
||||
|
||||
if (command.getAlias() != null && command.getAlias().length > 0) {
|
||||
availAlias.append("(");
|
||||
for (String str : command.getAlias()) {
|
||||
availAlias.append(str).append(",");
|
||||
}
|
||||
|
||||
if (!availAlias.isEmpty()) {
|
||||
availAlias.deleteCharAt(availAlias.lastIndexOf(","));
|
||||
availAlias.append(")");
|
||||
}
|
||||
}
|
||||
|
||||
EmbedBuilder message;
|
||||
if (help.containsKey(command.getType())) {
|
||||
message = help.get(command.getType());
|
||||
@@ -161,7 +179,7 @@ public class MessageFunction {
|
||||
message.setColor(Color.GREEN);
|
||||
}
|
||||
|
||||
message.addField(Settings.getInstance().get("BOT_PREFIX") + command.getCommand() + " - Arguments: " + usage, description, false);
|
||||
message.addField(String.format("%s%s %s %s", Settings.getInstance().get("BOT_PREFIX"), command.getCommand(), availAlias, usage), description, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package netneutrality.utils;/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://xtremcommunity.com/
|
||||
* https://discord.gg/CdFcyQ
|
||||
*/
|
||||
|
||||
|
||||
import netneutrality.GuildManager;
|
||||
import netneutrality.music.MusicManager;
|
||||
import netneutrality.music.TrackScheduler;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Map;
|
||||
|
||||
public class UnsafeShutdown {
|
||||
public static boolean SAFE = false;
|
||||
|
||||
//TODO: finish
|
||||
private static void saveGuildsState() {
|
||||
Map<String, GuildManager> managers = GuildManager.getManagers();
|
||||
|
||||
for (GuildManager manager : managers.values()) {
|
||||
File state = new File("state.json");
|
||||
|
||||
try {
|
||||
if (!state.exists()) {
|
||||
state.createNewFile();
|
||||
}
|
||||
|
||||
FileWriter writer = new FileWriter(state);
|
||||
JSONArray array = new JSONArray();
|
||||
|
||||
|
||||
|
||||
MusicManager musicManager = MusicManager.get(manager.getGuild());
|
||||
TrackScheduler trackScheduler = musicManager.getScheduler();
|
||||
|
||||
JSONObject music = new JSONObject();
|
||||
|
||||
music.put("current_channel", "");
|
||||
music.put("current_topic", "");
|
||||
music.put("current_topic", "");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveState() {
|
||||
saveGuildsState();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user