Add voteskip command and update music player

This commit is contained in:
anthorob committed 2022-02-08 18:34:06 -05:00
1 parent dbf6fd549c
commit 048b645e61
41 files changed
+779 -308

No files matched your search

+135 -131
View File
@@ -1,151 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xtremcommunity.discord</groupId>
<artifactId>netneutrality</artifactId>
<version>1.0.0</version>
<name>netneutrality-discord-bot</name>
<description>Discord bot</description>
<packaging>jar</packaging>
<groupId>com.xtremcommunity.discord</groupId>
<artifactId>netneutrality</artifactId>
<version>1.0.0</version>
<name>netneutrality-discord-bot</name>
<description>Discord bot</description>
<packaging>jar</packaging>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>17</release>
<encoding>UTF-8</encoding>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>17</release>
<encoding>UTF-8</encoding>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>netneutrality.MusicBot</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>netneutrality.MusicBot</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>netneutrality.MusicBot</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>netneutrality</finalName>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>netneutrality.MusicBot</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>netneutrality</finalName>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
<repository>
<id>dv8tion</id>
<name>m2-dv8tion</name>
<url>https://m2.dv8tion.net/releases</url>
</repository>
<repository>
<id>dv8tion</id>
<name>m2-dv8tion</name>
<url>https://m2.dv8tion.net/releases</url>
</repository>
</repositories>
</repositories>
<dependencies>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>4.4.0_350</version>
</dependency>
<dependencies>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>4.4.0_350</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.sedmelluq</groupId>
<artifactId>lavaplayer</artifactId>
<version>1.3.78</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.sedmelluq</groupId>
<artifactId>lavaplayer</artifactId>
<version>1.3.78</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
+51 -6
View File
@@ -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();
}
+8 -17
View File
@@ -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();
}
}
+5 -23
View File
@@ -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());
}
}
@@ -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();
}
@@ -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);
}
}
@@ -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();
}
}