diff --git a/pom.xml b/pom.xml
index 1450722..4dd727e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.xtremcommunity.discord
netneutrality
- 1.0.0
+ 2.0.0
netneutrality-discord-bot
Discord bot
jar
@@ -108,7 +108,7 @@
net.dv8tion
JDA
- 4.4.0_350
+ 5.0.0-alpha.18
diff --git a/src/main/java/netneutrality/NetNeutrality.java b/src/main/java/netneutrality/NetNeutrality.java
index 80e804d..95acf1e 100644
--- a/src/main/java/netneutrality/NetNeutrality.java
+++ b/src/main/java/netneutrality/NetNeutrality.java
@@ -9,9 +9,10 @@ import net.dv8tion.jda.api.requests.GatewayIntent;
import netneutrality.core.CommandManager;
import netneutrality.core.LogHandler;
import netneutrality.db.DBController;
-import netneutrality.handler.hooks.guilds.ServerJoinHandler;
-import netneutrality.handler.hooks.message.EditHandler;
-import netneutrality.handler.hooks.message.MessageReceivedHandler;
+import netneutrality.hooks.SlashCommandHooks;
+import netneutrality.hooks.guilds.ServerJoinHandler;
+import netneutrality.hooks.message.EditHandler;
+import netneutrality.hooks.message.MessageReceivedHandler;
import netneutrality.http.server.WebApi;
import netneutrality.music.MusicManager;
import netneutrality.thread.BaseThreadFactory;
@@ -37,8 +38,9 @@ public class NetNeutrality {
options.setDsn(sentryDsn);
options.setEnvironment(env);
options.setTracesSampleRate(1.0);
- options.setDebug(env.equals("dev"));
- options.setRelease("netneutrality@2.0.0-alpha");
+ //options.setDebug(env.equals("dev"));
+ options.setDebug(false);
+ options.setRelease("netneutrality@2.0.0");
});
if ("dev".equals(env)) {
@@ -50,6 +52,7 @@ public class NetNeutrality {
CommandManager.init();
MusicManager.initPlayerManager();
jda.addEventListener(new MessageReceivedHandler(), new EditHandler(), new ServerJoinHandler());
+ jda.addEventListener(new SlashCommandHooks());
new WebApi(Integer.parseInt(Settings.getInstance().get("API_PORT", "9000")));
jda.getPresence().setActivity(Activity.watching("you"));
@@ -58,11 +61,10 @@ public class NetNeutrality {
}
public static void initJDA() {
- // When upgrading JDA -> GatewayIntent.MESSAGE_CONTENT
try {
jda = JDABuilder
.createDefault(Settings.getInstance().get("BOT_TOKEN"))
- .enableIntents(GatewayIntent.GUILD_MEMBERS, GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.GUILD_VOICE_STATES)
+ .enableIntents(GatewayIntent.GUILD_MEMBERS, GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.GUILD_VOICE_STATES, GatewayIntent.MESSAGE_CONTENT)
.setActivity(Activity.watching("me load..."))
.build();
jda.awaitReady();
diff --git a/src/main/java/netneutrality/command/AbstractCommand.java b/src/main/java/netneutrality/command/AbstractCommand.java
index 252a597..68575d2 100644
--- a/src/main/java/netneutrality/command/AbstractCommand.java
+++ b/src/main/java/netneutrality/command/AbstractCommand.java
@@ -2,17 +2,34 @@ package netneutrality.command;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
-import net.dv8tion.jda.api.entities.TextChannel;
+import net.dv8tion.jda.api.entities.MessageChannel;
+import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
+import netneutrality.core.context.MessageCommandContext;
public abstract class AbstractCommand implements ICommand {
+ @Override
+ public boolean isSlashCommand() {
+ return true;
+ }
+
+ @Override
+ public DefaultMemberPermissions getSlashCommandPermission() {
+ return DefaultMemberPermissions.ENABLED;
+ }
+
@Override
public boolean canBeExecutedBy(Guild guild, Member member) {
return true;
}
@Override
- public boolean canBeExecutedFrom(Guild guild, TextChannel channel) {
+ public boolean canBeExecutedFrom(Guild guild, MessageChannel channel) {
return true;
}
+
+ @Override
+ public void execute(MessageCommandContext context) {
+ // Prefer slash commands
+ }
}
diff --git a/src/main/java/netneutrality/command/AbstractMusicCommand.java b/src/main/java/netneutrality/command/AbstractMusicCommand.java
index 44bbf20..61ec61a 100644
--- a/src/main/java/netneutrality/command/AbstractMusicCommand.java
+++ b/src/main/java/netneutrality/command/AbstractMusicCommand.java
@@ -6,10 +6,7 @@ package netneutrality.command;
* https://discord.gg/CdFcyQ
*/
-import net.dv8tion.jda.api.entities.Guild;
-import net.dv8tion.jda.api.entities.Member;
-import net.dv8tion.jda.api.entities.Role;
-import net.dv8tion.jda.api.entities.TextChannel;
+import net.dv8tion.jda.api.entities.*;
import netneutrality.core.GuildManager;
import netneutrality.db.GSettings;
import netneutrality.utils.UserFunction;
@@ -21,6 +18,11 @@ public abstract class AbstractMusicCommand extends AbstractCommand {
return false;
}
+ @Override
+ public boolean isGuildOnly() {
+ return true;
+ }
+
@Override
public CommandType getType() {
return CommandType.MUSIC;
@@ -49,7 +51,10 @@ public abstract class AbstractMusicCommand extends AbstractCommand {
}
@Override
- public boolean canBeExecutedFrom(Guild guild, TextChannel channel) {
+ public boolean canBeExecutedFrom(Guild guild, MessageChannel channel) {
+ if (channel.getType() != ChannelType.TEXT)
+ return false;
+
String channelDb = GuildManager.getManager(guild).getSetting(GSettings.MUSIC_CHANNEL);
if (channelDb != null && !channelDb.isEmpty()) {
diff --git a/src/main/java/netneutrality/command/CommandUsage.java b/src/main/java/netneutrality/command/CommandUsage.java
deleted file mode 100644
index b5b82dc..0000000
--- a/src/main/java/netneutrality/command/CommandUsage.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package netneutrality.command;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import java.util.Arrays;
-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[] values;
- private final String description;
-
- public Argument(Type t, String[] values, String desc) {
- if (t == Type.REQUIRED && (values == null || values.length == 0))
- throw new IllegalArgumentException("Command usage: values can't be null if type is required");
-
- if (t == Type.OPTIONAL && (desc == null || desc.isEmpty()))
- throw new IllegalArgumentException("Command usage: description can't be null if type is optional");
-
- this.type = t;
- this.values = values;
- this.description = desc;
- }
-
- public String[] getValues() {
- return values;
- }
-
- public String getDescription() {
- return description;
- }
-
- public Type getType() {
- return type;
- }
- }
-
- private final AbstractCommand command;
- private final Set args = new HashSet<>();
-
- public CommandUsage(AbstractCommand command, Argument... arguments) {
- this.command = command;
- Collections.addAll(args, arguments);
- }
-
- public CommandUsage addArgument(Argument argument) {
- args.add(argument);
- return this;
- }
-
- public static CommandUsage create(AbstractCommand command, Argument... arguments) {
- return new CommandUsage(command, arguments);
- }
-
- public AbstractCommand getCommand() {
- return command;
- }
-
- public int getRequiredArguments() {
- return args.size();
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("Available arguments: ").append(args.size()).append("\n");
- sb.append(command.getCommandName()).append(" ");
- for (Argument arg : args) {
- sb.append("<");
- if (arg.getType() == Argument.Type.OPTIONAL) {
- sb.append("optional: ");
-
- if (arg.getValues() != null || arg.getValues().length != 0)
- sb.append(Arrays.toString(arg.getValues())).append(": ");
-
- sb.append(arg.getDescription());
- }
-
- if (arg.getType() == Argument.Type.REQUIRED) {
- sb.append("required: ").append(Arrays.toString(arg.getValues()));
-
- if (arg.getDescription() != null && !arg.getDescription().isEmpty())
- sb.append(": ").append(arg.getDescription());
- }
-
- sb.append("> ");
- }
-
- return sb.toString();
- }
-}
diff --git a/src/main/java/netneutrality/command/ICommand.java b/src/main/java/netneutrality/command/ICommand.java
index 91fed50..bb8b86c 100644
--- a/src/main/java/netneutrality/command/ICommand.java
+++ b/src/main/java/netneutrality/command/ICommand.java
@@ -8,51 +8,37 @@ package netneutrality.command;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
-import net.dv8tion.jda.api.entities.TextChannel;
-import netneutrality.core.context.CommandContext;
-import netneutrality.exceptions.CommandErrorException;
-import netneutrality.exceptions.CommandExecutionException;
+import net.dv8tion.jda.api.entities.MessageChannel;
+import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
public interface ICommand {
- /**
- * @return if the command needs administrator privilege
- */
boolean needAdmin();
- /**
- * @return if the command should be loaded at runtime
- */
boolean isEnabled();
- /**
- * The command name that a user will write in a channel
- *
- * @return the name of the command.
- */
+ boolean isGuildOnly();
+
+ boolean isSlashCommand();
+
String getCommandName();
- /**
- * @return all the aliases the command has
- */
- String[] getAlias();
-
- CommandUsage getUsage();
-
String getDescription();
+ DefaultMemberPermissions getSlashCommandPermission();
+
+ void registerSlashCommandOptions(SlashCommandData data);
+
CommandType getType();
boolean canBeExecutedBy(Guild guild, Member member);
- boolean canBeExecutedFrom(Guild guild, TextChannel channel);
+ boolean canBeExecutedFrom(Guild guild, MessageChannel channel);
- /**
- * Command is executed with this function.
- *
- * @param context The context for the command
- * @throws CommandErrorException Used to reply with a message in the text channel where the command was executed
- * @throws CommandExecutionException Logs the error internally, without sending a message
- */
- void execute(CommandContext context) throws CommandErrorException, CommandExecutionException;
+ void execute(MessageCommandContext context);
+
+ void execute(SlashCommandContext context);
}
diff --git a/src/main/java/netneutrality/command/Visibility.java b/src/main/java/netneutrality/command/Visibility.java
deleted file mode 100644
index 71b7d73..0000000
--- a/src/main/java/netneutrality/command/Visibility.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package netneutrality.command;
-
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import net.dv8tion.jda.api.entities.MessageChannel;
-import net.dv8tion.jda.api.entities.PrivateChannel;
-import net.dv8tion.jda.api.entities.TextChannel;
-
-public enum Visibility {
-
- PRIVATE, CHANNEL, BOTH;
-
- public static boolean check(MessageChannel channel, Visibility v) {
- if (v == BOTH && (channel instanceof TextChannel || channel instanceof PrivateChannel))
- return true;
-
- if (v == PRIVATE && channel instanceof PrivateChannel)
- return true;
-
- if (v == CHANNEL && channel instanceof TextChannel)
- return true;
-
- return false;
- }
-}
diff --git a/src/main/java/netneutrality/command/admin/BlacklistCommand.java b/src/main/java/netneutrality/command/admin/BlacklistCommand.java
new file mode 100644
index 0000000..6762834
--- /dev/null
+++ b/src/main/java/netneutrality/command/admin/BlacklistCommand.java
@@ -0,0 +1,111 @@
+package netneutrality.command.admin;
+/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
+import netneutrality.command.AbstractCommand;
+import netneutrality.command.CommandType;
+import netneutrality.core.LogHandler;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
+import netneutrality.db.DBController;
+import netneutrality.db.controllers.DBBlacklist;
+import netneutrality.db.entities.OBlacklist;
+
+import java.util.ArrayList;
+
+public class BlacklistCommand extends AbstractCommand {
+
+ @Override
+ public boolean needAdmin() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isGuildOnly() {
+ return true;
+ }
+
+ @Override
+ public String getCommandName() {
+ return "blacklist";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Manages the blacklist of your server.";
+ }
+
+ @Override
+ public DefaultMemberPermissions getSlashCommandPermission() {
+ return DefaultMemberPermissions.DISABLED;
+ }
+
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+ data.addSubcommands(
+ new SubcommandData("get", "Get all blacklisted words for this guild"),
+ new SubcommandData("add", "Add a word to the blacklist")
+ .addOption(OptionType.STRING, "word", "Word to add"),
+ new SubcommandData("remove", "Remove a word from the blacklist")
+ .addOption(OptionType.STRING, "word", "Word to remove")
+ );
+ }
+
+ @Override
+ public CommandType getType() {
+ return CommandType.ADMINISTRATION;
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
+
+ }
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ String sub = context.getEvent().getCommandPath().split("/")[1];
+ DBBlacklist controller = DBController.get(DBBlacklist.class);
+ String word = context.getEvent().getOption("word", "", OptionMapping::getAsString);
+ context.ackAndWait(true);
+
+ switch (sub) {
+ case "get" -> {
+
+ context.getHook().editOriginal("Retrieving list, please wait...").queue(t -> {
+ ArrayList blacklists = new ArrayList<>();
+ try {
+ blacklists = controller.getBlacklistForGuild(context.getGuild());
+ } catch (Exception e) {
+ LogHandler.log(e);
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (OBlacklist bl : blacklists) {
+ sb.append(bl.getWord()).append(" -> ").append(bl.getEnabled() ? "enabled" : "disabled").append("\n");
+ }
+
+ t.editMessage("List of blacklisted words for this server [" + context.getGuild().getName() + "] :\n" + (blacklists.isEmpty() ? "No word found" : sb.toString())).queue();
+
+ });
+ }
+ case "add" -> controller.add(word, context);
+ case "remove" -> controller.delete(word, context);
+ case "disable" -> controller.disable(word, context);
+ case "enable" -> controller.enable(word, context);
+ }
+ }
+}
diff --git a/src/main/java/netneutrality/command/admin/PurgeCommand.java b/src/main/java/netneutrality/command/admin/PurgeCommand.java
new file mode 100644
index 0000000..a4ddd6d
--- /dev/null
+++ b/src/main/java/netneutrality/command/admin/PurgeCommand.java
@@ -0,0 +1,95 @@
+package netneutrality.command.admin;
+/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import net.dv8tion.jda.api.entities.GuildMessageChannel;
+import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.OptionData;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import netneutrality.command.AbstractCommand;
+import netneutrality.command.CommandType;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
+import netneutrality.utils.ChannelMessagePurger;
+
+public class PurgeCommand extends AbstractCommand {
+
+ @Override
+ public boolean needAdmin() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isGuildOnly() {
+ return true;
+ }
+
+ @Override
+ public String getCommandName() {
+ return "purge";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Delete messages from the channel you are currently on";
+ }
+
+ @Override
+ public DefaultMemberPermissions getSlashCommandPermission() {
+ return DefaultMemberPermissions.DISABLED;
+ }
+
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ data.addOptions(
+ new OptionData(OptionType.INTEGER, "to-purge", "Number of messages to delete (max 2500)", true)
+ .setRequiredRange(1, 2500));
+ }
+
+ @Override
+ public CommandType getType() {
+ return CommandType.ADMINISTRATION;
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
+ if (context.getArgs().length == 1) {
+ GuildMessageChannel messageChannel = context.getEvent().getGuildChannel();
+ ChannelMessagePurger channelMessagePurger = ChannelMessagePurger.getPurger(messageChannel);
+ channelMessagePurger.purgeMessages(context, Integer.parseInt(context.getArgument(0)));
+ } else {
+ context.getChannel().sendMessage("Failed to delete messages!").queue();
+ }
+ }
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ int toDelete = context.getEvent().getOption("to-purge", 0, OptionMapping::getAsInt);
+ context.ackAndWait(true);
+
+ if (toDelete > 0) {
+ GuildMessageChannel messageChannel = context.getEvent().getGuildChannel();
+ ChannelMessagePurger channelMessagePurger = ChannelMessagePurger.getPurger(messageChannel);
+ boolean lock = channelMessagePurger.canLockBeAcquired();
+ channelMessagePurger.purgeMessages(context, toDelete);
+
+ context.replyEphemeral("Processing purge command.. This can take some time.");
+
+ if (!lock) {
+ context.replyEphemeral("Another purge is currently in progress on this channel, please wait before purging again");
+ }
+ }
+ }
+}
diff --git a/src/main/java/netneutrality/command/basic/HelpCommand.java b/src/main/java/netneutrality/command/basic/HelpCommand.java
index 94e9e2f..8ec34f4 100644
--- a/src/main/java/netneutrality/command/basic/HelpCommand.java
+++ b/src/main/java/netneutrality/command/basic/HelpCommand.java
@@ -6,15 +6,14 @@ package netneutrality.command.basic;
* https://discord.gg/CdFcyQ
*/
-import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.CommandManager;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.utils.MessageFunction;
-import netneutrality.utils.UserFunction;
import java.util.List;
@@ -30,59 +29,47 @@ public class HelpCommand extends AbstractCommand {
return true;
}
+ @Override
+ public boolean isGuildOnly() {
+ return false;
+ }
+
@Override
public String getCommandName() {
return "help";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"command"}, "Name of command to get help with")
- );
- }
-
@Override
public String getDescription() {
return "Get every command with its usage";
}
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ }
+
@Override
public CommandType getType() {
return CommandType.UTILITY;
}
@Override
- public void execute(CommandContext context) {
+ public void execute(MessageCommandContext context) {
if (context.getArgs().length == 0) {
- List help = MessageFunction.buildHelpMessage(CommandManager.commands, UserFunction.isAdmin(context.getGuildUser()));
+ List help = MessageFunction.buildHelpMessage(context.getGuildUser());
- context.reply(new MessageBuilder().append(context.getDiscordUser()).append(" help has been sent your way!").build());
+ context.reply(new MessageCreateBuilder().addContent(context.getDiscordUser().getAsMention()).addContent(" help has been sent your way!").build());
context.replyPrivate(help);
}
- if (context.getArgs().length == 1) {
- String cmd = context.getArgument(0);
-
- if (CommandManager.commands.containsKey(cmd) || CommandManager.commandsAlias.containsKey(cmd)) {
- AbstractCommand c = CommandManager.commands.containsKey(cmd) ? CommandManager.commands.get(cmd) : CommandManager.commandsAlias.get(cmd);
-
- if (c.needAdmin() && !UserFunction.isAdmin(context.getGuildUser())) {
- context.replyPrivate("Command [" + c.getCommandName() + "] requires admin privileges");
- }
-
- MessageEmbed help = MessageFunction.buildHelpMessage(c);
- context.reply(new MessageBuilder().append(context.getDiscordUser()).append(" help has been sent your way!").build());
- context.replyPrivate(help);
- }
- }
-
+ }
+ @Override
+ public void execute(SlashCommandContext context) {
+ List help = MessageFunction.buildHelpMessage(context.getGuildUser());
+ context.replyEphemeral("Help has been sent in DM!");
+ context.sendMessageInPrivate(help);
}
}
diff --git a/src/main/java/netneutrality/command/basic/PingCommand.java b/src/main/java/netneutrality/command/basic/PingCommand.java
index 6551022..8a943a9 100644
--- a/src/main/java/netneutrality/command/basic/PingCommand.java
+++ b/src/main/java/netneutrality/command/basic/PingCommand.java
@@ -6,10 +6,11 @@ package netneutrality.command.basic;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
public class PingCommand extends AbstractCommand {
@@ -23,35 +24,40 @@ public class PingCommand extends AbstractCommand {
return true;
}
+ @Override
+ public boolean isGuildOnly() {
+ return false;
+ }
+
@Override
public String getCommandName() {
return "ping";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
- }
-
@Override
public String getDescription() {
return "Pong!";
}
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ }
+
@Override
public CommandType getType() {
return CommandType.UTILITY;
}
@Override
- public void execute(CommandContext context) {
+ public void execute(MessageCommandContext context) {
if (context.getArgs().length == 0)
context.reply(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing()));
}
+ @Override
+ public void execute(SlashCommandContext context) {
+ context.reply(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing()));
+ }
+
}
diff --git a/src/main/java/netneutrality/command/bot/ConfigureCommand.java b/src/main/java/netneutrality/command/bot/ConfigureCommand.java
index a038154..42b1cc8 100644
--- a/src/main/java/netneutrality/command/bot/ConfigureCommand.java
+++ b/src/main/java/netneutrality/command/bot/ConfigureCommand.java
@@ -8,18 +8,27 @@ package netneutrality.command.bot;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.TextChannel;
+import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
+import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.OptionData;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
+import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
import netneutrality.core.GuildManager;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.db.GSettings;
import netneutrality.music.MusicManager;
-import java.util.Arrays;
import java.util.List;
+import java.util.Map;
public class ConfigureCommand extends AbstractCommand {
+
@Override
public boolean needAdmin() {
return true;
@@ -30,21 +39,14 @@ public class ConfigureCommand extends AbstractCommand {
return true;
}
+ @Override
+ public boolean isGuildOnly() {
+ return true;
+ }
+
@Override
public String getCommandName() {
- return "configure";
- }
-
- @Override
- public String[] getAlias() {
- return new String[]{"conf"};
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"music-role", "music-channel", "music-volume", "music-topic", "debug"}, "")
- );
+ return "config";
}
@Override
@@ -52,13 +54,33 @@ public class ConfigureCommand extends AbstractCommand {
return "Used to configure the bot on this server";
}
+ @Override
+ public DefaultMemberPermissions getSlashCommandPermission() {
+ return DefaultMemberPermissions.DISABLED;
+ }
+
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+ data.addSubcommands(
+ new SubcommandData("music-volume", "Volume for the music player")
+ .addOptions(new OptionData(OptionType.INTEGER, "volume", "Integer between 0 and 100", true)
+ .setRequiredRange(0, 100)),
+ new SubcommandData("error-logging", "Send errors to #error and/or #log channel")
+ .addOption(OptionType.BOOLEAN, "debug", "Enable or disable the fonctionnality", true),
+ new SubcommandData("music-role", "Role needed to use music commands")
+ .addOption(OptionType.ROLE, "role", "Name of role", true),
+ new SubcommandData("music-channel", "Only allow music commands on this channel")
+ .addOption(OptionType.CHANNEL, "channel", "Leave empty to allow everywhere")
+ );
+ }
+
@Override
public CommandType getType() {
return CommandType.ADMINISTRATION;
}
@Override
- public void execute(CommandContext context) {
+ public void execute(MessageCommandContext context) {
String[] args = context.getArgs();
GuildManager guildManager = GuildManager.getManager(context.getGuild());
@@ -86,7 +108,7 @@ public class ConfigureCommand extends AbstractCommand {
context.reply("Successful reset of the role");
}
- List roles = context.getMessage().getMentionedRoles();
+ List roles = context.getMessage().getMentions().getRoles();
if (roles.size() == 1) {
Role role = roles.get(0);
if (role.getGuild().getId().equals(context.getGuild().getId())) {
@@ -119,7 +141,7 @@ public class ConfigureCommand extends AbstractCommand {
context.reply("Successful reset of the channel");
}
- List channels = context.getMessage().getMentionedChannels();
+ List channels = context.getMessage().getMentions().getChannels(TextChannel.class);
if (channels.size() == 1) {
TextChannel channel = channels.get(0);
if (channel.getGuild().getId().equals(context.getGuild().getId())) {
@@ -157,28 +179,6 @@ public class ConfigureCommand extends AbstractCommand {
}
}
- // Music topic change
- if (context.getArgument(0).equals("music-topic")) {
- if (args.length == 1) {
- boolean enabled = "1".equals(guildManager.getSetting(GSettings.MUSIC_TOPIC));
-
- context.reply("Set currently playing track in text channel topic: %s", (enabled ? "enabled" : "disabled"));
- context.reply("Use 'conf music-topic 0/1' to toggle between states (0 = disabled, 1 = enabled).");
- }
-
- if (args.length == 2) {
- String str = args[1];
- boolean enabled = "1".equals(guildManager.getSetting(GSettings.MUSIC_TOPIC));
- if (str.equals("0") || str.equals("1")) {
- guildManager.setSettingValue(GSettings.MUSIC_TOPIC, str);
- enabled = "1".equals(str);
- }
-
- context.reply("Set currently playing track in text channel topic is now %s for this guild", (enabled ? "enabled" : "disabled"));
-
- }
- }
-
// Debug
if (context.getArgument(0).equals("debug")) {
if (args.length == 1) {
@@ -204,34 +204,84 @@ public class ConfigureCommand extends AbstractCommand {
}
}
+ }
+ }
- // Prefix
- if (context.getArgument(0).equals("prefix")) {
- String allowedPrefixes = "!$%?&*";
+ @Override
+ public void execute(SlashCommandContext context) {
+ String sub = context.getEvent().getCommandPath().split("/")[1];
+ GuildManager guildManager = GuildManager.getManager(context.getGuild());
+ context.ackAndWait(true);
- if (args.length == 1) {
- String prefix = guildManager.getSetting(GSettings.PREFIX);
+ if ("music-role".equals(sub)) {
+ Role role = context.getEvent().getOption("role", OptionMapping::getAsRole);
+ assert role != null;
- context.reply("Current prefix for commands: '%s'", prefix);
- context.reply("Allowed prefixes: %s", Arrays.toString(allowedPrefixes.toCharArray()));
+ if (role.getPosition() == -1) {
+ guildManager.setSettingValue(GSettings.MUSIC_ROLE, null);
+ context.replyEphemeral("Everyone can now use music commands");
+ return;
+ }
- }
+ if (role.getGuild().getId().equals(context.getGuild().getId())) {
+ guildManager.setSettingValue(GSettings.MUSIC_ROLE, role.getId());
+ context.replyEphemeral("Successfully set %s as the role needed for music command", role.getAsMention());
+ return;
+ }
+ }
- if (args.length == 2) {
- String prefix = args[1].trim();
+ if ("music-channel".equals(sub)) {
+ GuildChannelUnion channel = context.getEvent().getOption("channel", OptionMapping::getAsChannel);
- if (prefix.length() == 1 && allowedPrefixes.contains(prefix)) {
- guildManager.setSettingValue(GSettings.PREFIX, prefix);
-
- context.reply("Prefix for commands is now '%s'", prefix);
- } else {
- context.reply("Allowed prefixes: %s", Arrays.toString(allowedPrefixes.toCharArray()));
- }
+ if (channel == null) {
+ guildManager.setSettingValue(GSettings.MUSIC_CHANNEL, null);
+ context.replyEphemeral("No channel restrictions for music commands");
+ return;
+ }
+ if (channel instanceof TextChannel) {
+ if (channel.getGuild().getId().equals(context.getGuild().getId())) {
+ guildManager.setSettingValue(GSettings.MUSIC_CHANNEL, channel.getId());
+ context.replyEphemeral("Successfully set %s as the channel required to execute music command", channel.getAsMention());
+ return;
}
}
- } else {
- context.reply(getUsage());
+
+ }
+
+ if ("music-volume".equals(sub)) {
+ int volume = context.getEvent().getOption("volume", 30, OptionMapping::getAsInt);
+ guildManager.setSettingValue(GSettings.MUSIC_VOLUME, String.valueOf(volume));
+ MusicManager.get(context.getGuild()).setVolume(volume);
+
+ context.replyEphemeral("Default volume for music player is now %d", volume);
+ return;
+ }
+
+ if ("debug".equals(sub)) {
+ boolean debug = context.getEvent().getOption("debug", true, OptionMapping::getAsBoolean);
+
+ guildManager.setDebug(debug);
+ context.reply("Error logging is now %s for this guild", (debug ? "enabled" : "disabled"));
+ return;
+ }
+
+ if ("show-all".equals(sub)) {
+ Map settings = guildManager.getSettings();
+ MessageCreateBuilder builder = new MessageCreateBuilder();
+
+ for (GSettings o : GSettings.values()) {
+ String value = o.getDefaultValue();
+
+ if (settings.containsKey(o.getName())) {
+ value = settings.get(o.getName());
+ }
+
+ builder.addContent(o.getName()).addContent(": ").addContent(value);
+ builder.addContent("\n");
+ }
+
+ context.replyEphemeral(builder.build());
}
}
}
diff --git a/src/main/java/netneutrality/command/crypto/BitcoinPriceCommand.java b/src/main/java/netneutrality/command/crypto/BitcoinPriceCommand.java
deleted file mode 100644
index c30adaf..0000000
--- a/src/main/java/netneutrality/command/crypto/BitcoinPriceCommand.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package netneutrality.command.crypto;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import netneutrality.command.AbstractCommand;
-import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.LogHandler;
-import netneutrality.core.context.CommandContext;
-import netneutrality.http.WebModule;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.text.NumberFormat;
-import java.util.Currency;
-import java.util.Locale;
-
-public class BitcoinPriceCommand extends AbstractCommand {
-
- private final String baseURL = "https://min-api.cryptocompare.com/data/price";
- private final String crypto = "BTC";
-
- @Override
- public boolean needAdmin() {
- return false;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @Override
- public String getCommandName() {
- return "bitcoin";
- }
-
- @Override
- public String[] getAlias() {
- return new String[]{"btc"};
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"currency"}, "defaults to USD")
- );
- }
-
- @Override
- public String getDescription() {
- return "Get the price of bitcoin";
- }
-
- @Override
- public CommandType getType() {
- return CommandType.CRYPTO;
- }
-
- @Override
- public void execute(CommandContext context) {
- String[] args = context.getArgs();
- String currency = "USD";
-
- if (args.length == 1) {
- try {
- currency = Currency.getInstance(args[0].toUpperCase()).getCurrencyCode();
- } catch (IllegalArgumentException exception) {
- context.reply("Please enter a valid currency");
- return;
- }
- }
-
- String finalCurrency = currency;
- context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> {
- String price;
- Locale usa = new Locale("en", "US");
- NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
- dollarFormat.setMaximumFractionDigits(24);
-
- try {
- WebModule http = new WebModule(String.format("%s?fsym=%s&tsyms=%s", baseURL, crypto, finalCurrency.toUpperCase())).request();
- JSONObject json = http.getAsObject();
- if (json.isEmpty() || (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error"))) {
- t.editMessage(String.format("Failed getting price of %s", crypto)).queue();
- return;
- }
-
- price = dollarFormat.format(json.getDouble(finalCurrency));
- t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
- } catch (JSONException | IllegalArgumentException | ArithmeticException e) {
- t.editMessage(String.format("Error getting price of %s!", crypto)).queue();
- LogHandler.log(e);
- }
- });
- }
-}
diff --git a/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java b/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java
index bce1e27..ffa0098 100644
--- a/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java
+++ b/src/main/java/netneutrality/command/crypto/CryptoPriceCommand.java
@@ -6,11 +6,14 @@ package netneutrality.command.crypto;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
import netneutrality.core.LogHandler;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.http.WebModule;
import org.json.JSONException;
import org.json.JSONObject;
@@ -33,36 +36,34 @@ public class CryptoPriceCommand extends AbstractCommand {
return true;
}
+ @Override
+ public boolean isGuildOnly() {
+ return false;
+ }
+
@Override
public String getCommandName() {
return "crypto";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"crypto"}, "Symbol of crypto"),
- new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"currency"}, "defaults to USD")
- );
- }
-
@Override
public String getDescription() {
return "Get the price of cryptocurrencies";
}
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+ data.addOption(OptionType.STRING, "symbol", "The crypto symbol to fetch price for", true);
+ data.addOption(OptionType.STRING, "currency", "In which currency should the price be displayed");
+ }
+
@Override
public CommandType getType() {
return CommandType.CRYPTO;
}
@Override
- public void execute(CommandContext context) {
+ public void execute(MessageCommandContext context) {
String[] args = context.getArgs();
String currency = "USD";
@@ -102,4 +103,46 @@ public class CryptoPriceCommand extends AbstractCommand {
});
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ Locale usa = new Locale("en", "US");
+ NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
+ dollarFormat.setMaximumFractionDigits(24);
+
+ String symbol = context.getEvent().getOption("symbol", OptionMapping::getAsString);
+ String currency = context.getEvent().getOption("currency", "USD", OptionMapping::getAsString);
+
+ try {
+ currency = Currency.getInstance(currency).getCurrencyCode();
+ } catch (IllegalArgumentException exception) {
+ context.reply("Please enter a valid currency");
+ return;
+ }
+
+ String finalCurrency = currency.toUpperCase();
+ context.getEvent().deferReply().queue(interactionHook -> {
+ try {
+
+ WebModule http = new WebModule(String.format("%s?fsym=%s&tsyms=%s", baseURL, symbol, finalCurrency)).request();
+ JSONObject json = http.getAsObject();
+
+ if (json.isEmpty() || (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error"))) {
+ interactionHook.editOriginal("Crypto doesn't exist.. yet").queue();
+ return;
+ }
+
+ double value = json.getDouble(finalCurrency);
+ String price = dollarFormat.format(value);
+
+ interactionHook.editOriginal(String.format("The current price of %s in %s is %s", symbol, finalCurrency, price)).queue();
+
+ } catch (JSONException | IllegalArgumentException | ArithmeticException e) {
+ interactionHook.editOriginal(String.format("Error getting price of %s!", symbol)).queue();
+ LogHandler.log(e);
+ }
+
+
+ });
+ }
}
diff --git a/src/main/java/netneutrality/command/crypto/EthereumPriceCommand.java b/src/main/java/netneutrality/command/crypto/EthereumPriceCommand.java
deleted file mode 100644
index a29ccf8..0000000
--- a/src/main/java/netneutrality/command/crypto/EthereumPriceCommand.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package netneutrality.command.crypto;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import netneutrality.command.AbstractCommand;
-import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.LogHandler;
-import netneutrality.core.context.CommandContext;
-import netneutrality.http.WebModule;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.text.NumberFormat;
-import java.util.Currency;
-import java.util.Locale;
-
-public class EthereumPriceCommand extends AbstractCommand {
-
- private final String baseURL = "https://min-api.cryptocompare.com/data/price";
- private final String crypto = "ETH";
-
- @Override
- public boolean needAdmin() {
- return false;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @Override
- public String getCommandName() {
- return "ethereum";
- }
-
- @Override
- public String[] getAlias() {
- return new String[]{"eth"};
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"currency"}, "defaults to USD")
- );
- }
-
- @Override
- public String getDescription() {
- return "Get the ethereum price";
- }
-
- @Override
- public CommandType getType() {
- return CommandType.CRYPTO;
- }
-
- @Override
- public void execute(CommandContext context) {
- String[] args = context.getArgs();
- String currency = "USD";
-
- if (args.length == 1) {
- try {
- currency = Currency.getInstance(args[0].toUpperCase()).getCurrencyCode();
- } catch (IllegalArgumentException exception) {
- context.reply("Please enter a valid currency");
- return;
- }
- }
-
- String finalCurrency = currency;
- context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> {
- String price;
- Locale usa = new Locale("en", "US");
- NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
- dollarFormat.setMaximumFractionDigits(24);
-
- try {
- WebModule http = new WebModule(String.format("%s?fsym=%s&tsyms=%s", baseURL, crypto, finalCurrency.toUpperCase())).request();
- JSONObject json = http.getAsObject();
- if (json.isEmpty() || (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error"))) {
- t.editMessage(String.format("Failed getting price of %s", crypto)).queue();
- return;
- }
-
- price = dollarFormat.format(json.getDouble(finalCurrency));
- t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
- } catch (JSONException | IllegalArgumentException e) {
- t.editMessage(String.format("Error getting price of %s!", crypto)).queue();
- LogHandler.log(e);
- }
- });
- }
-}
diff --git a/src/main/java/netneutrality/command/crypto/LitecoinPriceCommand.java b/src/main/java/netneutrality/command/crypto/LitecoinPriceCommand.java
deleted file mode 100644
index c782d67..0000000
--- a/src/main/java/netneutrality/command/crypto/LitecoinPriceCommand.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package netneutrality.command.crypto;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import netneutrality.command.AbstractCommand;
-import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.LogHandler;
-import netneutrality.core.context.CommandContext;
-import netneutrality.http.WebModule;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.text.NumberFormat;
-import java.util.Currency;
-import java.util.Locale;
-
-public class LitecoinPriceCommand extends AbstractCommand {
-
- private final String baseURL = "https://min-api.cryptocompare.com/data/price";
- private final String crypto = "LTC";
-
- @Override
- public boolean needAdmin() {
- return false;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @Override
- public String getCommandName() {
- return "litecoin";
- }
-
- @Override
- public String[] getAlias() {
- return new String[]{"ltc"};
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"currency"}, "defaults to USD")
- );
- }
-
- @Override
- public String getDescription() {
- return "Get the litecoin price";
- }
-
- @Override
- public CommandType getType() {
- return CommandType.CRYPTO;
- }
-
- @Override
- public void execute(CommandContext context) {
- String[] args = context.getArgs();
- String currency = "USD";
-
- if (args.length == 1) {
- try {
- currency = Currency.getInstance(args[0].toUpperCase()).getCurrencyCode();
- } catch (IllegalArgumentException exception) {
- context.reply("Please enter a valid currency");
- return;
- }
- }
-
- String finalCurrency = currency;
- context.getChannel().sendMessage("Retreiving price, please wait...").queue(t -> {
- String price;
- Locale usa = new Locale("en", "US");
- NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
- dollarFormat.setMaximumFractionDigits(24);
-
- try {
- WebModule http = new WebModule(String.format("%s?fsym=%s&tsyms=%s", baseURL, crypto, finalCurrency.toUpperCase())).request();
- JSONObject json = http.getAsObject();
- if (json.isEmpty() || (json.has("Response") && json.getString("Response").equalsIgnoreCase("Error"))) {
- t.editMessage(String.format("Failed getting price of %s", crypto)).queue();
- return;
- }
-
- price = dollarFormat.format(json.getDouble(finalCurrency));
- t.editMessage(String.format("The current price of %s in %s is %s", crypto, finalCurrency, price)).queue();
- } catch (JSONException | IllegalArgumentException | ArithmeticException e) {
- t.editMessage(String.format("Error getting price of %s!", crypto)).queue();
- LogHandler.log(e);
- }
- });
- }
-}
diff --git a/src/main/java/netneutrality/command/message/BlacklistCommand.java b/src/main/java/netneutrality/command/message/BlacklistCommand.java
deleted file mode 100644
index d442c2e..0000000
--- a/src/main/java/netneutrality/command/message/BlacklistCommand.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package netneutrality.command.message;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import netneutrality.command.AbstractCommand;
-import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.LogHandler;
-import netneutrality.core.context.CommandContext;
-import netneutrality.db.DBController;
-import netneutrality.db.controllers.DBBlacklist;
-import netneutrality.db.entities.OBlacklist;
-
-import java.util.ArrayList;
-
-public class BlacklistCommand extends AbstractCommand {
-
- @Override
- public boolean needAdmin() {
- return true;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @Override
- public String getCommandName() {
- return "blacklist";
- }
-
- @Override
- public String[] getAlias() {
- return new String[]{"bl"};
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
- }
-
- @Override
- public String getDescription() {
- return "Manages the blacklist of your server.";
- }
-
- @Override
- public CommandType getType() {
- return CommandType.ADMINISTRATION;
- }
-
- @Override
- public void execute(CommandContext context) {
- String[] args = context.getArgs();
- DBBlacklist controller = DBController.get(DBBlacklist.class);
-
- if (args.length > 0 && args.length < 3) {
- String word = (args.length == 2 ? args[1] : "");
-
- switch (args[0]) {
- case "get" -> {
-
- context.getChannel().sendMessage("Retrieving list, please wait...").queue(t -> {
- ArrayList blacklists = new ArrayList<>();
- try {
- blacklists = controller.getBlacklistForGuild(context);
- } catch (Exception e) {
- LogHandler.log(e);
- }
-
- StringBuilder sb = new StringBuilder();
- for (OBlacklist bl : blacklists) {
- sb.append(bl.getWord()).append(" -> ").append(bl.getEnabled() ? "enabled" : "disabled").append("\n");
- }
-
- t.editMessage("List of blacklisted words for this server [" + context.getGuild().getName() + "] :\n" + (blacklists.isEmpty() ? "No word found" : sb.toString())).queue();
-
- });
- }
- case "add" -> controller.add(word, context);
- case "remove" -> controller.delete(word, context);
- case "disable" -> controller.disable(word, context);
- case "enable" -> controller.enable(word, context);
- }
- }
- }
-
-}
diff --git a/src/main/java/netneutrality/command/message/PruneCommand.java b/src/main/java/netneutrality/command/message/PruneCommand.java
deleted file mode 100644
index 6cc7848..0000000
--- a/src/main/java/netneutrality/command/message/PruneCommand.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package netneutrality.command.message;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import netneutrality.command.AbstractCommand;
-import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
-import netneutrality.utils.ChannelFunction;
-
-public class PruneCommand extends AbstractCommand {
-
- @Override
- public boolean needAdmin() {
- return true;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @Override
- public String getCommandName() {
- return "prune";
- }
-
- @Override
- public String[] getAlias() {
- return new String[]{"purge"};
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"number"}, "Max 2499")
- );
- }
-
- @Override
- public String getDescription() {
- return "Delete n messages from the channel you are currently on";
- }
-
- @Override
- public CommandType getType() {
- return CommandType.ADMINISTRATION;
- }
-
- @Override
- public void execute(CommandContext context) {
- if (context.getArgs().length == 1)
- ChannelFunction.bulkDeleteMessage(context.getChannel(), Integer.parseInt(context.getArgument(0)));
- else
- context.getChannel().sendMessage("Failed to delete messages!").queue();
- }
-
-}
diff --git a/src/main/java/netneutrality/command/music/BitconnectCommand.java b/src/main/java/netneutrality/command/music/BitconnectCommand.java
index c66aeba..b2e0269 100644
--- a/src/main/java/netneutrality/command/music/BitconnectCommand.java
+++ b/src/main/java/netneutrality/command/music/BitconnectCommand.java
@@ -7,10 +7,11 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
import netneutrality.command.CommandType;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
public class BitconnectCommand extends AbstractMusicCommand {
@@ -25,19 +26,14 @@ public class BitconnectCommand extends AbstractMusicCommand {
return "bitconnect";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
- }
-
@Override
public String getDescription() {
- return null;
+ return "Ready to invest?";
+ }
+
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
}
@Override
@@ -46,10 +42,19 @@ public class BitconnectCommand extends AbstractMusicCommand {
}
@Override
- public void execute(CommandContext context) {
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
player.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, false, true);
- context.getMessage().delete().queue();
+ context.deleteMessage();
+ }
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager player = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+
+ player.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, false, true);
+ context.reply("Ready to invest?");
}
}
diff --git a/src/main/java/netneutrality/command/music/DeleteQueueCommand.java b/src/main/java/netneutrality/command/music/ClearQueueCommand.java
similarity index 67%
rename from src/main/java/netneutrality/command/music/DeleteQueueCommand.java
rename to src/main/java/netneutrality/command/music/ClearQueueCommand.java
index a44a62a..54a1b96 100644
--- a/src/main/java/netneutrality/command/music/DeleteQueueCommand.java
+++ b/src/main/java/netneutrality/command/music/ClearQueueCommand.java
@@ -7,15 +7,15 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
-import netneutrality.exceptions.CommandErrorException;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
import netneutrality.utils.MessageFunction;
import netneutrality.utils.MusicUtils;
-public class DeleteQueueCommand extends AbstractMusicCommand {
+public class ClearQueueCommand extends AbstractMusicCommand {
@Override
public boolean needAdmin() {
@@ -29,19 +29,7 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
@Override
public String getCommandName() {
- return "deletequeue";
- }
-
- @Override
- public String[] getAlias() {
- return new String[] {"delq", "delqueue", "clear"};
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.OPTIONAL, new String[] {"track #", "all"}, "")
- );
+ return "clearqueue";
}
@Override
@@ -50,7 +38,12 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (!MusicUtils.checkIfConnected(player, context))
@@ -58,7 +51,7 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
if (context.getArgs().length == 0) {
context.reply("Select the track you want to delete from the queue (track# or all)");
- context.reply(MessageFunction.buildViewQueueMessage(player, context.getGuildUser(), true));
+ context.reply(MessageFunction.buildViewQueueMessage(player, true));
}
if (context.getArgs().length > 0) {
@@ -88,9 +81,26 @@ public class DeleteQueueCommand extends AbstractMusicCommand {
}
} catch (NumberFormatException e) {
- throw new CommandErrorException("Please enter a number", context, e);
+ context.reply("Please enter a number");
}
}
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+
+ if (!MusicUtils.checkIfConnected(manager, context))
+ return;
+
+ int queueSize = manager.getQueueSize();
+ if (queueSize > 0) {
+ manager.getScheduler().getQueueManager().clearQueue();
+ context.reply(String.format("Removed %d track%s from the queue", queueSize--, (queueSize > 1 ? "s" : "")));
+ } else {
+ context.reply("Queue is empty!");
+ }
+ }
}
diff --git a/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java b/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java
index 57ee083..68f4738 100644
--- a/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java
+++ b/src/main/java/netneutrality/command/music/CurrentlyPlayingCommand.java
@@ -7,9 +7,10 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
import netneutrality.utils.MessageFunction;
import netneutrality.utils.MusicUtils;
@@ -23,17 +24,7 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand {
@Override
public String getCommandName() {
- return "playing";
- }
-
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
+ return "nowplaying";
}
@Override
@@ -42,14 +33,29 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand {
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+ // no arguments
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (MusicUtils.checkIfConnected(player, context) && player.isCurrentlyPlaying()) {
- context.reply(MessageFunction.buildCurrentlyPlayingMessage(player, context.getGuildUser()));
+ context.reply(MessageFunction.buildCurrentlyPlayingMessage(player));
} else {
- context.reply("Player is not playing any tracks right now");
+ context.reply("Bot isn't playing any tracks right now");
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+
+ if (MusicUtils.checkIfConnected(manager, context) && manager.isCurrentlyPlaying()) {
+ context.reply(MessageFunction.buildCurrentlyPlayingMessage(manager));
+ }
+ }
}
diff --git a/src/main/java/netneutrality/command/music/JoinCommand.java b/src/main/java/netneutrality/command/music/JoinCommand.java
index c12784e..10d044a 100644
--- a/src/main/java/netneutrality/command/music/JoinCommand.java
+++ b/src/main/java/netneutrality/command/music/JoinCommand.java
@@ -8,9 +8,10 @@ package netneutrality.command.music;
*/
import net.dv8tion.jda.api.entities.VoiceChannel;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.exceptions.CommandExecutionException;
import netneutrality.music.MusicManager;
@@ -26,30 +27,25 @@ public class JoinCommand extends AbstractMusicCommand {
return "join";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
- }
-
@Override
public String getDescription() {
- return "Make the bot join the current voice channel (if no music is playing, bot will disconnect automatically)";
+ return "Make the bot join your current voice channel";
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (context.getGuildUser().getVoiceState() == null) {
throw new CommandExecutionException("Voice state is null, this should not happen", context, null);
}
- if (!context.getGuildUser().getVoiceState().inVoiceChannel()) {
+ if (!context.getGuildUser().getVoiceState().inAudioChannel()) {
context.reply("You are not in a voice channel");
return;
}
@@ -59,11 +55,37 @@ public class JoinCommand extends AbstractMusicCommand {
return;
}
- VoiceChannel vChannel = context.getGuildUser().getVoiceState().getChannel();
+ VoiceChannel vChannel = (VoiceChannel) context.getGuildUser().getVoiceState().getChannel();
if (vChannel != null) {
player.connect(vChannel);
context.reply("Joining current voice channel");
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager player = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+
+ if (context.getGuildUser().getVoiceState() == null) {
+ throw new CommandExecutionException("Voice state is null, this should not happen", context, null);
+ }
+
+ if (!context.getGuildUser().getVoiceState().inAudioChannel()) {
+ context.reply("You are not in a voice channel");
+ return;
+ }
+
+ if (player.isConnected()) {
+ context.reply("Player is already in a voice channel");
+ return;
+ }
+
+ VoiceChannel vChannel = (VoiceChannel) context.getGuildUser().getVoiceState().getChannel();
+ if (vChannel != null) {
+ player.connect(vChannel);
+ context.reply("Joining current voice channel");
+ }
+ }
}
diff --git a/src/main/java/netneutrality/command/music/LeaveCommand.java b/src/main/java/netneutrality/command/music/LeaveCommand.java
index 0b1df1f..f62e07d 100644
--- a/src/main/java/netneutrality/command/music/LeaveCommand.java
+++ b/src/main/java/netneutrality/command/music/LeaveCommand.java
@@ -7,13 +7,15 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils;
public class LeaveCommand extends AbstractMusicCommand {
+
@Override
public boolean needAdmin() {
return true;
@@ -29,23 +31,18 @@ public class LeaveCommand extends AbstractMusicCommand {
return "leave";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
- }
-
@Override
public String getDescription() {
return "Make the bot leave the voice channel";
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (MusicUtils.checkIfConnected(player, context)) {
@@ -53,4 +50,15 @@ public class LeaveCommand extends AbstractMusicCommand {
context.reply("Leaving voice channel and clearing queue");
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager player = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+
+ if (MusicUtils.checkIfConnected(player, context)) {
+ player.leave();
+ context.reply("Leaving voice channel and clearing queue");
+ }
+ }
}
diff --git a/src/main/java/netneutrality/command/music/PlayCommand.java b/src/main/java/netneutrality/command/music/PlayCommand.java
index 9c219ac..0ef8ec5 100644
--- a/src/main/java/netneutrality/command/music/PlayCommand.java
+++ b/src/main/java/netneutrality/command/music/PlayCommand.java
@@ -7,9 +7,12 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
public class PlayCommand extends AbstractMusicCommand {
@@ -24,34 +27,32 @@ public class PlayCommand extends AbstractMusicCommand {
return "play";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(
- this,
- new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"url"}, "Youtube/Soundcloud link or search string")
- );
- }
-
@Override
public String getDescription() {
return "Get the party going!";
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+ data.addOption(OptionType.STRING, "query", "URL or search query", true);
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (context.getArgs().length > 0) {
player.play(context.getMessageText(), context, false, false);
- } else {
- //TODO: resume queue
- context.reply(getUsage());
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ String query = context.getEvent().getOption("query", OptionMapping::getAsString);
+ context.ackAndWait();
+
+ manager.play(query, context, false, false);
+ }
}
diff --git a/src/main/java/netneutrality/command/music/QueueCommand.java b/src/main/java/netneutrality/command/music/QueueCommand.java
new file mode 100644
index 0000000..5bc534c
--- /dev/null
+++ b/src/main/java/netneutrality/command/music/QueueCommand.java
@@ -0,0 +1,180 @@
+package netneutrality.command.music;
+/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.OptionData;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
+import netneutrality.command.AbstractMusicCommand;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
+import netneutrality.music.MusicManager;
+import netneutrality.utils.MessageFunction;
+import netneutrality.utils.MusicUtils;
+
+public class QueueCommand extends AbstractMusicCommand {
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @Override
+ public String getCommandName() {
+ return "queue";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Manage the music queue";
+ }
+
+ @Override
+ public DefaultMemberPermissions getSlashCommandPermission() {
+ return DefaultMemberPermissions.DISABLED;
+ }
+
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+ data.addSubcommands(
+ new SubcommandData("clear-all", "Clear all queued tracks"),
+ new SubcommandData("delete-track", "Remove a single track from the queue")
+ .addOptions(new OptionData(OptionType.INTEGER, "position", "Position of track", true)
+ .setMinValue(1)),
+ new SubcommandData("show-queue", "Display current queue"),
+ new SubcommandData("shuffle", "Shuffle the queue"),
+ new SubcommandData("from-user", "View tracks added by a user")
+ .addOption(OptionType.USER, "user", "Which user?", true),
+ new SubcommandData("remove-from-user", "Remove all tracks added by a user")
+ .addOption(OptionType.USER, "user", "Which user?", true)
+ );
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
+ MusicManager player = MusicManager.get(context.getGuild());
+
+ if (!MusicUtils.checkIfConnected(player, context))
+ return;
+
+ if (context.getArgs().length == 0) {
+ context.reply("Select the track you want to delete from the queue (track# or all)");
+ context.reply(MessageFunction.buildViewQueueMessage(player, true));
+ }
+
+ if (context.getArgs().length > 0) {
+
+ int queueSize = player.getQueueSize();
+ if (context.getArgument(0).equals("all")) {
+
+ if (queueSize > 0) {
+ player.getScheduler().getQueueManager().clearQueue();
+ context.reply(String.format("Removed %d track%s from the queue", queueSize--, (queueSize > 1 ? "s" : "")));
+ } else {
+ context.reply("Queue is empty!");
+ }
+ } else {
+
+ try {
+ int num = Integer.parseInt(context.getArgument(0));
+
+ if (num > 0) {
+ if (player.removeFromQueue(num)) {
+ context.reply("Removed track #%d from the queue", num);
+ } else {
+ context.reply("Error while removing track #%d from the queue", num);
+ }
+ } else {
+ context.reply("Number out of range");
+ }
+
+ } catch (NumberFormatException e) {
+ context.reply("Please enter a number");
+ }
+ }
+ }
+ }
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+ String sub = context.getEvent().getCommandPath().split("/")[1];
+
+ if (!MusicUtils.checkIfConnected(manager, context)) {
+ return;
+ }
+
+ switch (sub) {
+ case "clear-all" -> {
+ int queueSize = manager.getQueueSize();
+
+ if (queueSize > 0) {
+ manager.getScheduler().getQueueManager().clearQueue();
+ context.reply(String.format("Removed %d track%s from the queue", queueSize--, (queueSize > 1 ? "s" : "")));
+ } else {
+ context.reply("Queue is already empty!");
+ }
+ }
+
+ case "delete-track" -> {
+ int position = context.getEvent().getOption("position", 0, OptionMapping::getAsInt);
+
+ if (position > 0) {
+ if (manager.removeFromQueue(position)) {
+ context.reply("Removed track #%d from the queue", position);
+ } else {
+ context.reply("Position is out of bounds");
+ }
+ }
+ }
+
+ case "show-queue" -> context.reply(MessageFunction.buildViewQueueMessage(manager, true));
+
+ case "shuffle" -> {
+ manager.getScheduler().getQueueManager().shuffle();
+ context.reply("Queue is now shuffled.");
+ }
+
+ case "from-user" -> {
+ Member user = context.getEvent().getOption("user", OptionMapping::getAsMember);
+ if (user == null) {
+ context.reply("The user isn't from this guild");
+ break;
+ }
+
+ context.reply(MessageFunction.buildUserTracksMessage(manager, user));
+ }
+
+ case "remove-from-user" -> {
+ Member member = context.getEvent().getOption("user", OptionMapping::getAsMember);
+ if (member == null) {
+ context.reply("The user isn't from this guild");
+ break;
+ }
+
+ int size = manager.getScheduler()
+ .getQueueManager()
+ .getQueueWithFilter(trackInfo -> member.equals(trackInfo.getRequester()))
+ .size();
+
+ if (size == 0) {
+ context.reply("No tracks added by user %s", member.getEffectiveName());
+ } else {
+ manager.getScheduler().getQueueManager().removeTracksFromUser(member);
+ context.reply("Removed all tracks from user %s", member.getEffectiveName());
+ }
+ }
+ }
+
+
+ }
+}
diff --git a/src/main/java/netneutrality/command/music/ShuffleCommand.java b/src/main/java/netneutrality/command/music/ShuffleCommand.java
new file mode 100644
index 0000000..57e3a2a
--- /dev/null
+++ b/src/main/java/netneutrality/command/music/ShuffleCommand.java
@@ -0,0 +1,45 @@
+package netneutrality.command.music;/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import netneutrality.command.AbstractMusicCommand;
+import netneutrality.core.context.SlashCommandContext;
+import netneutrality.music.MusicManager;
+import netneutrality.utils.MusicUtils;
+
+public class ShuffleCommand extends AbstractMusicCommand {
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @Override
+ public String getCommandName() {
+ return "shuffle";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Shuffle the music queue";
+ }
+
+ @Override
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ }
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+
+ if (MusicUtils.checkIfConnected(manager, context)) {
+ manager.getScheduler().getQueueManager().shuffle();
+ context.reply("Queue is now shuffled.");
+ }
+ }
+}
diff --git a/src/main/java/netneutrality/command/music/SkipCommand.java b/src/main/java/netneutrality/command/music/SkipCommand.java
index 18a6ae6..ac22c57 100644
--- a/src/main/java/netneutrality/command/music/SkipCommand.java
+++ b/src/main/java/netneutrality/command/music/SkipCommand.java
@@ -7,9 +7,13 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.OptionData;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils;
import netneutrality.utils.UserFunction;
@@ -26,30 +30,19 @@ public class SkipCommand extends AbstractMusicCommand {
return "skip";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(
- this,
- new CommandUsage.Argument(
- CommandUsage.Argument.Type.OPTIONAL,
- new String[]{"number"},
- "Number of tracks to skip"
- )
- );
- }
-
@Override
public String getDescription() {
- return "Used to skip to the next track in the queue (if no admin privileges, vote skip instead)";
+ return "Skip to the next track in the queue";
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+ data.addOptions(new OptionData(OptionType.INTEGER, "skip", "Number of tracks to skip")
+ .setMinValue(1));
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (!MusicUtils.checkIfConnected(player, context))
@@ -59,14 +52,14 @@ public class SkipCommand extends AbstractMusicCommand {
if (UserFunction.isAdmin(context.getGuildUser()) && context.getArgs().length > 0) {
try {
int skips = Integer.parseInt(context.getArgument(0));
- player.skip(skips);
+ player.getScheduler().getQueueManager().skip(skips);
context.reply("Skipping %s track%s", skips, (skips > 1 ? "s" : ""));
} catch (NumberFormatException e) {
context.reply("Please enter how many track(s) to skip");
}
} else {
- player.skip(1);
+ player.getScheduler().getQueueManager().skip(1);
context.reply("Skipping current track");
}
} else {
@@ -74,4 +67,21 @@ public class SkipCommand extends AbstractMusicCommand {
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ int skips = context.getEvent().getOption("skip", 0, OptionMapping::getAsInt);
+ context.ackAndWait();
+
+ if (!MusicUtils.checkIfConnected(manager, context)) {
+ if (skips > 0) {
+ context.reply("Skipping %s track%s", skips, (skips > 1 ? "s" : ""));
+ manager.getScheduler().getQueueManager().skip(skips);
+ } else {
+ context.reply("Skipping current track");
+ manager.getScheduler().getQueueManager().skip(1);
+ }
+ }
+ }
}
diff --git a/src/main/java/netneutrality/command/music/StopCommand.java b/src/main/java/netneutrality/command/music/StopCommand.java
index 89adceb..4d869e2 100644
--- a/src/main/java/netneutrality/command/music/StopCommand.java
+++ b/src/main/java/netneutrality/command/music/StopCommand.java
@@ -7,9 +7,10 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils;
import netneutrality.utils.UserFunction;
@@ -26,23 +27,18 @@ public class StopCommand extends AbstractMusicCommand {
return "stop";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
- }
-
@Override
public String getDescription() {
return "Stop the music player, keeping the current queue.";
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (!MusicUtils.checkIfConnected(player, context))
@@ -55,4 +51,15 @@ public class StopCommand extends AbstractMusicCommand {
context.reply("Stopping current track");
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+
+ if (MusicUtils.checkIfConnected(manager, context)) {
+ manager.stopTrack();
+ context.reply("Stopping music playback");
+ }
+ }
}
diff --git a/src/main/java/netneutrality/command/music/ViewQueueCommand.java b/src/main/java/netneutrality/command/music/ViewQueueCommand.java
index 87acb1e..429930a 100644
--- a/src/main/java/netneutrality/command/music/ViewQueueCommand.java
+++ b/src/main/java/netneutrality/command/music/ViewQueueCommand.java
@@ -6,9 +6,10 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
import netneutrality.utils.MessageFunction;
import netneutrality.utils.MusicUtils;
@@ -25,33 +26,44 @@ public class ViewQueueCommand extends AbstractMusicCommand {
return "viewqueue";
}
- @Override
- public String[] getAlias() {
- return new String[]{"viewq", "queue"};
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
- }
-
@Override
public String getDescription() {
return "Get the current queue for the music player";
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (MusicUtils.checkIfConnected(player, context)) {
int queueSize = player.getQueueSize();
if (queueSize > 0) {
- context.reply(MessageFunction.buildViewQueueMessage(player, context.getGuildUser(), true));
+ context.reply(MessageFunction.buildViewQueueMessage(player, true));
} else {
context.reply("Queue is empty!");
}
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ context.ackAndWait();
+
+ if (MusicUtils.checkIfConnected(manager, context)) {
+ int queueSize = manager.getQueueSize();
+
+ if (queueSize > 0) {
+ context.reply(MessageFunction.buildViewQueueMessage(manager, true));
+ } else {
+ context.reply("Queue is empty!");
+ }
+ }
+ }
}
diff --git a/src/main/java/netneutrality/command/music/VolumeCommand.java b/src/main/java/netneutrality/command/music/VolumeCommand.java
index 4010c1a..29bd9d2 100644
--- a/src/main/java/netneutrality/command/music/VolumeCommand.java
+++ b/src/main/java/netneutrality/command/music/VolumeCommand.java
@@ -7,9 +7,13 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.OptionData;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils;
import netneutrality.utils.UserFunction;
@@ -26,23 +30,19 @@ public class VolumeCommand extends AbstractMusicCommand {
return "volume";
}
- @Override
- public String[] getAlias() {
- return new String[] { "vol" };
- }
-
- @Override
- public CommandUsage getUsage() {
- return CommandUsage.create(this, new CommandUsage.Argument(CommandUsage.Argument.Type.REQUIRED, new String[] {"0-100"}, ""));
- }
-
@Override
public String getDescription() {
return "Sets the volume for the music player";
}
@Override
- public void execute(CommandContext context) {
+ public void registerSlashCommandOptions(SlashCommandData data) {
+ data.addOptions(new OptionData(OptionType.INTEGER, "volume", "Playback volume for this session", true)
+ .setRequiredRange(0, 100));
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
MusicManager player = MusicManager.get(context.getGuild());
if (!MusicUtils.checkIfConnected(player, context))
@@ -63,4 +63,15 @@ public class VolumeCommand extends AbstractMusicCommand {
}
}
}
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+ int volume = context.getEvent().getOption("volume", 30, OptionMapping::getAsInt);
+
+ if (MusicUtils.checkIfConnected(manager, context)) {
+ context.reply("Volume set to %s", volume);
+ manager.setVolume(volume);
+ }
+ }
}
diff --git a/src/main/java/netneutrality/command/music/VoteSkipCommand.java b/src/main/java/netneutrality/command/music/VoteSkipCommand.java
index 65606b7..a27c612 100644
--- a/src/main/java/netneutrality/command/music/VoteSkipCommand.java
+++ b/src/main/java/netneutrality/command/music/VoteSkipCommand.java
@@ -6,9 +6,10 @@ package netneutrality.command.music;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import netneutrality.command.AbstractMusicCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.MessageCommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.music.MusicManager;
import netneutrality.utils.MusicUtils;
@@ -24,27 +25,31 @@ public class VoteSkipCommand extends AbstractMusicCommand {
return "voteskip";
}
- @Override
- public String[] getAlias() {
- return new String[0];
- }
-
- @Override
- public CommandUsage getUsage() {
- return null;
- }
-
@Override
public String getDescription() {
return "Cast a vote to skip the currently playing track";
}
@Override
- public void execute(CommandContext context) {
- MusicManager player = MusicManager.get(context.getGuild());
+ public void registerSlashCommandOptions(SlashCommandData data) {
- if (MusicUtils.checkIfConnected(player, context)) {
- player.voteSkip(context);
+ }
+
+ @Override
+ public void execute(MessageCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+
+ if (MusicUtils.checkIfConnected(manager, context)) {
+ manager.voteSkip(context);
+ }
+ }
+
+ @Override
+ public void execute(SlashCommandContext context) {
+ MusicManager manager = MusicManager.get(context.getGuild());
+
+ if (MusicUtils.checkIfConnected(manager, context)) {
+ manager.voteSkip(context);
}
}
}
diff --git a/src/main/java/netneutrality/core/CommandManager.java b/src/main/java/netneutrality/core/CommandManager.java
index c6ee03b..5cb70f4 100644
--- a/src/main/java/netneutrality/core/CommandManager.java
+++ b/src/main/java/netneutrality/core/CommandManager.java
@@ -7,6 +7,11 @@ package netneutrality.core;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
+import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
+import netneutrality.NetNeutrality;
import netneutrality.command.AbstractCommand;
import org.reflections.Reflections;
import org.slf4j.Logger;
@@ -14,26 +19,27 @@ import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Set;
public class CommandManager {
private final static Logger logger = LoggerFactory.getLogger(CommandManager.class);
public static final HashMap commands = new HashMap<>();
- public static final HashMap commandsAlias = new HashMap<>();
public static void init() {
initCommands();
- initAlias();
+ registerSlashCommands();
}
public static boolean isValidCommand(String commandString) {
- return commands.containsKey(commandString) || commandsAlias.containsKey(commandString);
+ return commands.containsKey(commandString);
}
public static AbstractCommand getCommand(String commandString) {
- return commands.containsKey(commandString) ? commands.get(commandString) : commandsAlias.get(commandString);
+ return commands.get(commandString);
}
private static void initCommands() {
@@ -65,14 +71,23 @@ public class CommandManager {
logger.info("Loaded " + commands.size() + " commands!");
}
- private static void initAlias() {
+ private static void registerSlashCommands() {
+ CommandListUpdateAction commandListUpdateAction = NetNeutrality.getJDA().updateCommands();
+ List slashCommands = new ArrayList<>();
for (AbstractCommand command : commands.values()) {
- for (String alias : command.getAlias()) {
- if (!commandsAlias.containsKey(alias))
- commandsAlias.put(alias, command);
+ if (!command.isEnabled() || !command.isSlashCommand()) {
+ continue;
}
- }
- }
+ SlashCommandData data = Commands.slash(command.getCommandName(), command.getDescription());
+ data.setDefaultPermissions(command.getSlashCommandPermission());
+ data.setGuildOnly(command.isGuildOnly());
+ command.registerSlashCommandOptions(data);
+
+ slashCommands.add(data);
+ }
+
+ commandListUpdateAction.addCommands(slashCommands).queue();
+ }
}
diff --git a/src/main/java/netneutrality/core/GuildManager.java b/src/main/java/netneutrality/core/GuildManager.java
index 63e951d..32708b4 100644
--- a/src/main/java/netneutrality/core/GuildManager.java
+++ b/src/main/java/netneutrality/core/GuildManager.java
@@ -17,8 +17,6 @@ import netneutrality.db.controllers.DBMessage;
import netneutrality.db.entities.OBlacklist;
import netneutrality.db.entities.OGuild;
import netneutrality.db.entities.OGuildSetting;
-import netneutrality.handler.ratelimiter.IMessageRateLimiter;
-import netneutrality.handler.ratelimiter.MessageRateLimiterImpl;
import netneutrality.thread.ThreadManager;
import netneutrality.utils.JpaUtils;
import netneutrality.utils.MessageFunction;
@@ -42,12 +40,10 @@ public class GuildManager {
private final Set blacklistCache = new HashSet<>();
private final Guild guild;
private OGuild guildEntity;
- private final IMessageRateLimiter rateLimiter;
private GuildManager(Guild guild) {
this.guild = guild;
this.guildEntity = loadGuildFromDb(guild.getId());
- this.rateLimiter = new MessageRateLimiterImpl();
managers.put(guild.getId(), this);
reloadBlacklistCache();
@@ -61,7 +57,6 @@ public class GuildManager {
this.guild = temp;
this.guildEntity = loadGuildFromDb(guild.getId());
- this.rateLimiter = new MessageRateLimiterImpl();
managers.put(guild.getId(), this);
reloadBlacklistCache();
@@ -97,10 +92,6 @@ public class GuildManager {
return guildEntity.getDebug();
}
- public IMessageRateLimiter getRateLimiter() {
- return rateLimiter;
- }
-
public Guild getGuild() {
return guild;
}
diff --git a/src/main/java/netneutrality/core/LogHandler.java b/src/main/java/netneutrality/core/LogHandler.java
index 2165707..3208447 100644
--- a/src/main/java/netneutrality/core/LogHandler.java
+++ b/src/main/java/netneutrality/core/LogHandler.java
@@ -10,7 +10,6 @@ import io.sentry.Sentry;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.TextChannel;
import netneutrality.core.context.CommandContext;
-import netneutrality.exceptions.CommandErrorException;
import netneutrality.exceptions.CommandException;
import netneutrality.exceptions.CommandExecutionException;
import netneutrality.utils.MessageFunction;
@@ -27,12 +26,6 @@ public class LogHandler {
* @param e The exceptions to log
*/
public static void log(Exception e) {
- if (e instanceof CommandErrorException) {
- sendMessageToChannel((CommandErrorException) e);
- logInternally((CommandErrorException) e);
- return;
- }
-
if (e instanceof CommandExecutionException) {
Sentry.captureException(e);
logInternally((CommandExecutionException) e);
@@ -82,9 +75,4 @@ public class LogHandler {
}
}
}
-
- private static void sendMessageToChannel(CommandErrorException error) {
- CommandContext context = error.getCommandContext();
- context.reply(error.getMessage());
- }
}
diff --git a/src/main/java/netneutrality/core/context/CommandContext.java b/src/main/java/netneutrality/core/context/CommandContext.java
index 40d3395..cf74a97 100644
--- a/src/main/java/netneutrality/core/context/CommandContext.java
+++ b/src/main/java/netneutrality/core/context/CommandContext.java
@@ -1,231 +1,51 @@
-package netneutrality.core.context;
-/*
+package netneutrality.core.context;/*
* Copyright (c) anthorob
*
* https://xtremcommunity.com/
* https://discord.gg/CdFcyQ
*/
-import io.sentry.Breadcrumb;
-import io.sentry.Sentry;
import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.*;
-import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
+import net.dv8tion.jda.api.events.Event;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
import netneutrality.command.AbstractCommand;
-import netneutrality.command.CommandUsage;
-import netneutrality.core.GuildManager;
-import netneutrality.core.LogHandler;
-import netneutrality.exceptions.CommandErrorException;
-import netneutrality.exceptions.CommandExecutionException;
-import netneutrality.thread.ThreadManager;
-import netneutrality.utils.Settings;
-import netneutrality.utils.UserFunction;
-import java.util.Collection;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
+public interface CommandContext {
-public class CommandContext {
+ AbstractCommand getCommand();
- private static final ExecutorService commandExecutor = ThreadManager.getExecutor("command-execution", ThreadManager.ExecutorType.FIXED);
+ Event getEvent();
- private AbstractCommand command;
- private final Message message;
- private final Guild guild;
- private final TextChannel channel;
- private final Member member;
- private final User user;
- private final JDA jda;
+ Guild getGuild();
- public CommandContext(Message message, Member member, User user, Guild guild, TextChannel channel, JDA jda) {
- this.message = message;
- this.member = member;
- this.guild = guild;
- this.channel = channel;
- this.user = user;
- this.jda = jda;
+ MessageChannel getChannel();
- io.sentry.protocol.User sentryUser = new io.sentry.protocol.User();
- sentryUser.setId(member.getId());
- sentryUser.setUsername(member.getEffectiveName());
- Sentry.setUser(sentryUser);
- Sentry.addBreadcrumb(Breadcrumb.info("New context for message id " + message.getId()));
- }
+ Member getGuildUser();
- public static CommandContext createContext(GuildMessageReceivedEvent event) {
- Message message = event.getMessage();
- Member member = event.getMember();
- User user = event.getAuthor();
- Guild guild = event.getGuild();
- TextChannel channel = event.getChannel();
- JDA jda = event.getJDA();
+ User getDiscordUser();
- return new CommandContext(message, member, user, guild, channel, jda);
- }
+ JDA getJDA();
- public String getArgument(int index) {
- return getArgs()[index];
- }
+ void deleteMessage();
- public String[] getArgs() {
- 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");
+ void reply(MessageCreateData message);
- if (args.length == 1 && args[0].isEmpty())
- args = new String[0];
+ void reply(String message);
- return args;
- }
+ void reply(MessageEmbed... embeds);
- public String getMessageText() {
- String msg = message.getContentDisplay().trim();
- msg = msg.substring(Settings.getInstance().get("BOT_PREFIX", "$").length()).trim();
- String cmd = msg.split(" ", 2)[0];
-
- return msg.replaceFirst("(" + cmd + ")(\s)?", "");
- }
-
- public Message getMessage() {
- return message;
- }
-
- public Guild getGuild() {
- return guild;
- }
-
- public TextChannel getChannel() {
- return channel;
- }
-
- public Member getGuildUser() {
- return member;
- }
-
- public User getDiscordUser() {
- return user;
- }
-
- public JDA getJDA() {
- return jda;
- }
-
- public AbstractCommand getCommand() {
- return command;
- }
-
- public GuildManager getGuildManager() {
- return GuildManager.getManager(guild);
- }
-
- public void reply(CommandUsage usage) {
- reply(new MessageBuilder(usage.toString()).build());
- }
-
- public void reply(String msg) {
- reply(new MessageBuilder(msg).build());
- }
-
- public void reply(String format, Object... arguments) {
+ default void reply(String format, Object... arguments) {
reply(String.format(format, arguments));
}
- public void reply(Message msg) {
- if (channel != null && channel.canTalk()) {
- channel.sendMessage(msg).queue();
- }
+ void replyToMessage(String message);
+
+ default void replyToMessage(MessageCreateData message) {
+ reply(message);
}
- public void reply(MessageEmbed embed, MessageEmbed... embeds) {
- if (channel != null && channel.canTalk()) {
- channel.sendMessageEmbeds(embed, embeds).queue();
- }
- }
-
- public void reply(Collection extends MessageEmbed> embeds) {
- if (channel != null && channel.canTalk()) {
- channel.sendMessageEmbeds(embeds).queue();
- }
- }
-
- public void replyToMessage(String msg) {
- if (channel != null && channel.canTalk() && message != null) {
- replyToMessage(new MessageBuilder(msg).build());
- }
- }
-
- public void replyToMessage(String format, Object... arguments) {
+ default void replyToMessage(String format, Object... arguments) {
replyToMessage(String.format(format, arguments));
}
-
- public void replyToMessage(Message msg) {
- if (channel != null && channel.canTalk() && message != null) {
- message.reply(msg).queue();
- }
- }
-
- public void replyPrivate(String msg) {
- replyPrivate(new MessageBuilder(msg).build());
- }
-
- public void replyPrivate(Message msg) {
- user.openPrivateChannel().flatMap(channel -> channel.sendMessage(msg)).queue();
- }
-
- public void replyPrivate(MessageEmbed embed, MessageEmbed... embeds) {
- user.openPrivateChannel().flatMap(channel -> channel.sendMessageEmbeds(embed, embeds)).queue();
- }
-
- public void replyPrivate(Collection extends MessageEmbed> embeds) {
- user.openPrivateChannel().flatMap(channel -> channel.sendMessageEmbeds(embeds)).queue();
- }
-
- public void deleteMessage() {
- if (message != null) {
- message.delete().queueAfter(1, TimeUnit.SECONDS);
- }
- }
-
- public boolean isMessageFromOwner() {
- return member.isOwner();
- }
-
- public boolean isMessageFromCreator() {
- String creatorId = Settings.getInstance().getCreatorId();
-
- return creatorId.equals(member.getId());
- }
-
- public void dispatch(AbstractCommand command) {
- this.command = command;
- //TODO: Add usage check
-
- Sentry.configureScope(scope -> {
- scope.setContexts("command", command.getCommandName());
- scope.setContexts("isAdmin", UserFunction.isAdmin(member));
- scope.setContexts("canBeExecuted", command.canBeExecutedBy(guild, member));
- scope.setTag("channel", channel.getId());
- scope.setTag("message", message.getId());
- scope.setTag("guild", guild.getId());
- });
-
- try {
- if (command.needAdmin() && !UserFunction.isAdmin(member)) {
- reply("You are not powerful enough, scrub");
- return;
- }
-
- if (command.canBeExecutedBy(guild, member)) {
- if (command.canBeExecutedFrom(guild, channel)) {
- command.execute(this);
- }
- }
- } catch (CommandErrorException | CommandExecutionException e) {
- LogHandler.log(e);
- } catch (Exception e) {
- LogHandler.log(new CommandExecutionException("Error during command execution", this, e));
- }
- }
}
diff --git a/src/main/java/netneutrality/core/context/MessageCommandContext.java b/src/main/java/netneutrality/core/context/MessageCommandContext.java
new file mode 100644
index 0000000..294ffcd
--- /dev/null
+++ b/src/main/java/netneutrality/core/context/MessageCommandContext.java
@@ -0,0 +1,225 @@
+package netneutrality.core.context;
+/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import io.sentry.Breadcrumb;
+import io.sentry.Sentry;
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.*;
+import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+import netneutrality.command.AbstractCommand;
+import netneutrality.core.GuildManager;
+import netneutrality.core.LogHandler;
+import netneutrality.exceptions.CommandExecutionException;
+import netneutrality.thread.ThreadManager;
+import netneutrality.utils.Settings;
+import netneutrality.utils.UserFunction;
+
+import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class MessageCommandContext implements CommandContext {
+
+ private static final ExecutorService commandExecutor = ThreadManager.getExecutor("command-execution", ThreadManager.ExecutorType.FIXED);
+
+ private AbstractCommand command;
+ private final MessageReceivedEvent event;
+ private final Message message;
+ private final Guild guild;
+ private final MessageChannel channel;
+ private final Member member;
+ private final User user;
+ private final JDA jda;
+
+ public MessageCommandContext(MessageReceivedEvent event, Message message, Member member, User user, Guild guild, MessageChannel channel, JDA jda) {
+ this.event = event;
+ this.message = message;
+ this.member = member;
+ this.guild = guild;
+ this.channel = channel;
+ this.user = user;
+ this.jda = jda;
+
+ io.sentry.protocol.User sentryUser = new io.sentry.protocol.User();
+ sentryUser.setId(member.getId());
+ sentryUser.setUsername(member.getEffectiveName());
+ Sentry.setUser(sentryUser);
+ Sentry.addBreadcrumb(Breadcrumb.info("New context for message id " + message.getId()));
+ }
+
+ public static MessageCommandContext createContext(MessageReceivedEvent event) {
+ Message message = event.getMessage();
+ Member member = event.getMember();
+ User user = event.getAuthor();
+ Guild guild = event.getGuild();
+ MessageChannel channel = event.getChannel();
+ JDA jda = event.getJDA();
+
+ return new MessageCommandContext(event, message, member, user, guild, channel, jda);
+ }
+
+ @Override
+ public MessageReceivedEvent getEvent() {
+ return event;
+ }
+
+ public String getArgument(int index) {
+ return getArgs()[index];
+ }
+
+ public String[] getArgs() {
+ 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");
+
+ if (args.length == 1 && args[0].isEmpty())
+ args = new String[0];
+
+ return args;
+ }
+
+ public String getMessageText() {
+ String msg = message.getContentDisplay().trim();
+ msg = msg.substring(Settings.getInstance().get("BOT_PREFIX", "$").length()).trim();
+ String cmd = msg.split(" ", 2)[0];
+
+ return msg.replaceFirst("(" + cmd + ")(\s)?", "");
+ }
+
+ public Message getMessage() {
+ return message;
+ }
+
+ public Guild getGuild() {
+ return guild;
+ }
+
+ public MessageChannel getChannel() {
+ return channel;
+ }
+
+ public Member getGuildUser() {
+ return member;
+ }
+
+ public User getDiscordUser() {
+ return user;
+ }
+
+ public JDA getJDA() {
+ return jda;
+ }
+
+ public AbstractCommand getCommand() {
+ return command;
+ }
+
+ public GuildManager getGuildManager() {
+ return GuildManager.getManager(guild);
+ }
+
+ public void reply(String message) {
+ reply(MessageCreateData.fromContent(message));
+ }
+
+ public void reply(String format, Object... arguments) {
+ reply(String.format(format, arguments));
+ }
+
+ public void reply(MessageEmbed... embeds) {
+ reply(MessageCreateData.fromEmbeds(embeds));
+ }
+
+ public void reply(MessageCreateData msg) {
+ if (channel != null && channel.canTalk()) {
+ channel.sendMessage(msg).queue();
+ }
+ }
+
+ @Override
+ public void replyToMessage(String message) {
+ replyToMessage(MessageCreateData.fromContent(message));
+ }
+
+ @Override
+ public void replyToMessage(String format, Object... arguments) {
+ replyToMessage(String.format(format, arguments));
+ }
+
+ public void replyToMessage(MessageCreateData msg) {
+ if (channel != null && channel.canTalk() && message != null) {
+ message.reply(msg).queue();
+ }
+ }
+
+ public void replyPrivate(String message) {
+ replyPrivate(MessageCreateData.fromContent(message));
+ }
+
+ public void replyPrivate(MessageCreateData msg) {
+ user.openPrivateChannel().flatMap(channel -> channel.sendMessage(msg)).queue();
+ }
+
+ public void replyPrivate(MessageEmbed... embeds) {
+ replyPrivate(MessageCreateData.fromEmbeds(embeds));
+ }
+
+ public void replyPrivate(Collection extends MessageEmbed> embeds) {
+ user.openPrivateChannel().flatMap(channel -> channel.sendMessageEmbeds(embeds)).queue();
+ }
+
+ @Override
+ public void deleteMessage() {
+ if (message != null) {
+ message.delete().queueAfter(1, TimeUnit.SECONDS);
+ }
+ }
+
+ public boolean isMessageFromOwner() {
+ return member.isOwner();
+ }
+
+ public boolean isMessageFromCreator() {
+ String creatorId = Settings.getInstance().getCreatorId();
+
+ return creatorId.equals(member.getId());
+ }
+
+ public void dispatch(AbstractCommand command) {
+ this.command = command;
+ //TODO: Add usage check
+
+ Sentry.configureScope(scope -> {
+ scope.setContexts("command", command.getCommandName());
+ scope.setContexts("isAdmin", UserFunction.isAdmin(member));
+ scope.setContexts("canBeExecuted", command.canBeExecutedBy(guild, member));
+ scope.setTag("channel", channel.getId());
+ scope.setTag("message", message.getId());
+ scope.setTag("guild", guild.getId());
+ });
+
+ try {
+ if (command.needAdmin() && !UserFunction.isAdmin(member)) {
+ reply("You are not powerful enough, scrub");
+ return;
+ }
+
+ if (command.canBeExecutedBy(guild, member)) {
+ if (command.canBeExecutedFrom(guild, channel)) {
+ command.execute(this);
+ }
+ }
+ } catch (CommandExecutionException e) {
+ LogHandler.log(e);
+ } catch (Exception e) {
+ LogHandler.log(new CommandExecutionException("Error during command execution", this, e));
+ }
+ }
+}
diff --git a/src/main/java/netneutrality/core/context/SlashCommandContext.java b/src/main/java/netneutrality/core/context/SlashCommandContext.java
new file mode 100644
index 0000000..bfab32e
--- /dev/null
+++ b/src/main/java/netneutrality/core/context/SlashCommandContext.java
@@ -0,0 +1,203 @@
+package netneutrality.core.context;/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import io.sentry.Sentry;
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.*;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.InteractionHook;
+import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+import net.dv8tion.jda.api.utils.messages.MessageEditData;
+import netneutrality.command.AbstractCommand;
+import netneutrality.core.CommandManager;
+import netneutrality.core.LogHandler;
+import netneutrality.exceptions.CommandExecutionException;
+import netneutrality.utils.UserFunction;
+
+import java.util.Collection;
+
+public class SlashCommandContext implements CommandContext {
+
+ private final SlashCommandInteractionEvent event;
+ private AbstractCommand command;
+ private final JDA jda;
+ private final Guild guild;
+ private final MessageChannel channel;
+ private final Member member;
+ private final User user;
+
+ private SlashCommandContext(JDA jda, SlashCommandInteractionEvent event, Guild guild, MessageChannel channel, Member member, User user) {
+ this.jda = jda;
+ this.event = event;
+ this.guild = guild;
+ this.channel = channel;
+ this.member = member;
+ this.user = user;
+ }
+
+ public static SlashCommandContext createContext(SlashCommandInteractionEvent event) {
+ Member member = event.getMember();
+ User user = event.getUser();
+ Guild guild = event.getGuild();
+ MessageChannel channel = event.getChannel();
+ JDA jda = event.getJDA();
+
+ return new SlashCommandContext(jda, event, guild, channel, member, user);
+ }
+
+ @Override
+ public SlashCommandInteractionEvent getEvent() {
+ return event;
+ }
+
+ @Override
+ public AbstractCommand getCommand() {
+ return command;
+ }
+
+ @Override
+ public JDA getJDA() {
+ return jda;
+ }
+
+ @Override
+ public Guild getGuild() {
+ return guild;
+ }
+
+ @Override
+ public MessageChannel getChannel() {
+ return channel;
+ }
+
+ @Override
+ public Member getGuildUser() {
+ return member;
+ }
+
+ @Override
+ public User getDiscordUser() {
+ return user;
+ }
+
+ @Override
+ public void deleteMessage() {
+ // not implemented
+ }
+
+ public void sendMessageInPrivate(String msg) {
+ sendMessageInPrivate(new MessageCreateBuilder().setContent(msg).build());
+ }
+
+ public void sendMessageInPrivate(MessageCreateData msg) {
+ user.openPrivateChannel().flatMap(channel -> channel.sendMessage(msg)).queue();
+ }
+
+ public void sendMessageInPrivate(MessageEmbed embed, MessageEmbed... embeds) {
+ user.openPrivateChannel().flatMap(channel -> channel.sendMessageEmbeds(embed, embeds)).queue();
+ }
+
+ public void sendMessageInPrivate(Collection extends MessageEmbed> embeds) {
+ user.openPrivateChannel().flatMap(channel -> channel.sendMessageEmbeds(embeds)).queue();
+ }
+
+ public void reply(MessageCreateData message) {
+ if (event.isAcknowledged()) {
+ getHook().editOriginal(MessageEditData.fromCreateData(message)).queue();
+ //getHook().sendMessage(message).setEphemeral(false).queue();
+ return;
+ }
+
+ event.reply(message).queue();
+ }
+
+ public void reply(MessageEmbed... embeds) {
+ reply(MessageCreateData.fromEmbeds(embeds));
+ }
+
+ @Override
+ public void reply(String message) {
+ reply(MessageCreateData.fromContent(message));
+ }
+
+ public void replyEphemeral(MessageCreateData message) {
+ if (event.isAcknowledged()) {
+ getHook().editOriginal(MessageEditData.fromCreateData(message)).queue();
+ //getHook().sendMessage(message).setEphemeral(true).queue();
+ return;
+ }
+
+ event.reply(message).setEphemeral(true).queue();
+ }
+
+ public void replyEphemeral(String format, Object... arguments) {
+ replyEphemeral(String.format(format, arguments));
+ }
+
+ public void replyEphemeral(String message) {
+ replyEphemeral(MessageCreateData.fromContent(message));
+ }
+
+ @Override
+ public void replyToMessage(String message) {
+ replyEphemeral(message);
+ }
+
+ public InteractionHook getHook() {
+ if (!event.isAcknowledged())
+ throw new RuntimeException("Interaction isn't acknowledged yet");
+
+ return event.getHook();
+ }
+
+ public void ackAndWait(boolean ephemeral) {
+ if (event.isAcknowledged())
+ throw new RuntimeException("Interaction is already acknowledged, please use getHook() instead.");
+
+ event.deferReply(ephemeral).queue();
+ }
+
+ public void ackAndWait() {
+ ackAndWait(false);
+ }
+
+ public void dispatchToCommand(String commandName) {
+ if (!CommandManager.isValidCommand(commandName)) {
+ return;
+ }
+
+ AbstractCommand command = CommandManager.getCommand(commandName);
+ this.command = command;
+
+ Sentry.configureScope(scope -> {
+ scope.setContexts("command", command.getCommandName());
+ scope.setContexts("isAdmin", UserFunction.isAdmin(member));
+ scope.setContexts("canBeExecuted", command.canBeExecutedBy(guild, member));
+ scope.setTag("channel", channel.getId());
+ scope.setTag("interactionId", event.getInteraction().getId());
+ scope.setTag("guild", guild.getId());
+ });
+
+ try {
+ if (command.needAdmin() && !UserFunction.isAdmin(member)) {
+ replyEphemeral("You are not powerful enough, scrub");
+ return;
+ }
+
+ if (command.canBeExecutedBy(guild, member)) {
+ command.execute(this);
+ }
+
+ } catch (CommandExecutionException exception) {
+ LogHandler.log(exception);
+ } catch (Exception exception) {
+ LogHandler.log(new CommandExecutionException("Error during command execution", this, exception));
+ }
+
+ }
+}
diff --git a/src/main/java/netneutrality/db/GSettings.java b/src/main/java/netneutrality/db/GSettings.java
index 8ec59c0..75bb292 100644
--- a/src/main/java/netneutrality/db/GSettings.java
+++ b/src/main/java/netneutrality/db/GSettings.java
@@ -6,17 +6,11 @@ package netneutrality.db;
* https://discord.gg/CdFcyQ
*/
-
-import netneutrality.utils.Settings;
-
public enum GSettings {
//TODO: description
- PREFIX("PREFIX", Settings.getInstance().get("BOT_PREFIX", "$")),
MUSIC_ROLE("MUSIC_ROLE", ""),
MUSIC_CHANNEL("MUSIC_CHANNEL", ""),
- MUSIC_VOLUME("MUSIC_VOLUME", "30"),
- MUSIC_TOPIC("MUSIC_TOPIC", "0"),
- BLACKLIST_CHANNELS("BLACKLIST_EXCLUDE_CHANNELS", "");
+ MUSIC_VOLUME("MUSIC_VOLUME", "30");
private final String name;
private final String defaultValue;
diff --git a/src/main/java/netneutrality/db/controllers/DBBlacklist.java b/src/main/java/netneutrality/db/controllers/DBBlacklist.java
index 725316e..b4cf87a 100644
--- a/src/main/java/netneutrality/db/controllers/DBBlacklist.java
+++ b/src/main/java/netneutrality/db/controllers/DBBlacklist.java
@@ -6,6 +6,7 @@ package netneutrality.db.controllers;
* https://discord.gg/CdFcyQ
*/
+import net.dv8tion.jda.api.entities.Guild;
import netneutrality.core.GuildManager;
import netneutrality.core.context.CommandContext;
import netneutrality.db.AbstractController;
@@ -104,8 +105,8 @@ public class DBBlacklist extends AbstractController {
session.close();
}
- public ArrayList getBlacklistForGuild(CommandContext context) {
- GuildManager guildManager = GuildManager.getManager(context.getGuild());
+ public ArrayList getBlacklistForGuild(Guild guild) {
+ GuildManager guildManager = GuildManager.getManager(guild);
Session session = getSessionFactory().openSession();
OGuild guildEntity = guildManager.getGuildEntity();
diff --git a/src/main/java/netneutrality/exceptions/CommandErrorException.java b/src/main/java/netneutrality/exceptions/CommandErrorException.java
deleted file mode 100644
index 0802ea2..0000000
--- a/src/main/java/netneutrality/exceptions/CommandErrorException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package netneutrality.exceptions;
-
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import netneutrality.core.context.CommandContext;
-
-/**
- * Used to reply with a message in the text channel where the command was executed
- */
-public class CommandErrorException extends CommandException {
-
- /**
- * Used to reply with a message in the text channel where the command was executed
- *
- * @param message Message to send to the channel
- * @param context The command context
- */
- public CommandErrorException(String message, CommandContext context, Throwable cause) {
- super(message, context, cause);
-
- }
-}
diff --git a/src/main/java/netneutrality/handler/hooks/message/ReactionHandler.java b/src/main/java/netneutrality/handler/hooks/message/ReactionHandler.java
deleted file mode 100644
index b309f44..0000000
--- a/src/main/java/netneutrality/handler/hooks/message/ReactionHandler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package netneutrality.handler.hooks.message;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import net.dv8tion.jda.api.entities.Member;
-import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent;
-import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent;
-import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionRemoveEvent;
-import net.dv8tion.jda.api.hooks.ListenerAdapter;
-import org.jetbrains.annotations.NotNull;
-
-public class ReactionHandler extends ListenerAdapter {
-
- @Override
- public void onGuildMessageReactionAdd(@NotNull GuildMessageReactionAddEvent event) {
- Member member = event.getMember();
- }
-
- @Override
- public void onGuildMessageReactionRemove(@NotNull GuildMessageReactionRemoveEvent event) {
- super.onGuildMessageReactionRemove(event);
- }
-
- @Override
- public void onGuildMessageUpdate(@NotNull GuildMessageUpdateEvent event) {
- super.onGuildMessageUpdate(event);
- }
-}
diff --git a/src/main/java/netneutrality/handler/ratelimiter/IMessageRateLimiter.java b/src/main/java/netneutrality/handler/ratelimiter/IMessageRateLimiter.java
deleted file mode 100644
index 4ce8d7b..0000000
--- a/src/main/java/netneutrality/handler/ratelimiter/IMessageRateLimiter.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package netneutrality.handler.ratelimiter;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import net.dv8tion.jda.api.entities.Member;
-import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.entities.TextChannel;
-
-public interface IMessageRateLimiter {
-
- void check(Member member, Message message, TextChannel channel);
-}
diff --git a/src/main/java/netneutrality/handler/ratelimiter/MessageRateLimiterImpl.java b/src/main/java/netneutrality/handler/ratelimiter/MessageRateLimiterImpl.java
deleted file mode 100644
index bd0d641..0000000
--- a/src/main/java/netneutrality/handler/ratelimiter/MessageRateLimiterImpl.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package netneutrality.handler.ratelimiter;
-/*
- * Copyright (c) anthorob
- *
- * https://xtremcommunity.com/
- * https://discord.gg/CdFcyQ
- */
-
-import net.dv8tion.jda.api.entities.Member;
-import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.entities.TextChannel;
-
-import java.time.OffsetDateTime;
-
-//TODO: to remove? or atleast make it useful
-public class MessageRateLimiterImpl implements IMessageRateLimiter {
- private final int messagePerSecond = 5;
- private static Member lastSender;
- private static OffsetDateTime timestamp;
- private static final long cooldown = 500000000L; // 1 seconds = 1000000000 nanoseconds
-
- public MessageRateLimiterImpl() {
-
- }
-
- @Override
- public void check(Member member, Message message, TextChannel channel) {
-
- if (lastSender == null || timestamp == null) {
- lastSender = member;
- timestamp = message.getTimeCreated();
- return;
- }
-
- if (member.getUser().getId().equals(lastSender.getUser().getId())) {
- if (message.getTimeCreated().minusNanos(cooldown).isBefore(timestamp)) {
- lastSender = member;
- timestamp = message.getTimeCreated();
- message.delete().queue();
- return;
- }
- }
-
- lastSender = member;
- timestamp = message.getTimeCreated();
- }
-}
diff --git a/src/main/java/netneutrality/hooks/SlashCommandHooks.java b/src/main/java/netneutrality/hooks/SlashCommandHooks.java
new file mode 100644
index 0000000..598f733
--- /dev/null
+++ b/src/main/java/netneutrality/hooks/SlashCommandHooks.java
@@ -0,0 +1,23 @@
+package netneutrality.hooks;
+/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.hooks.ListenerAdapter;
+import netneutrality.core.context.SlashCommandContext;
+import org.jetbrains.annotations.NotNull;
+
+public class SlashCommandHooks extends ListenerAdapter {
+
+ @Override
+ public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
+ String commandName = event.getName();
+
+ SlashCommandContext commandContext = SlashCommandContext.createContext(event);
+ commandContext.dispatchToCommand(commandName);
+ }
+}
diff --git a/src/main/java/netneutrality/handler/hooks/guilds/ServerJoinHandler.java b/src/main/java/netneutrality/hooks/guilds/ServerJoinHandler.java
similarity index 93%
rename from src/main/java/netneutrality/handler/hooks/guilds/ServerJoinHandler.java
rename to src/main/java/netneutrality/hooks/guilds/ServerJoinHandler.java
index de6a6a7..f556970 100644
--- a/src/main/java/netneutrality/handler/hooks/guilds/ServerJoinHandler.java
+++ b/src/main/java/netneutrality/hooks/guilds/ServerJoinHandler.java
@@ -1,4 +1,4 @@
-package netneutrality.handler.hooks.guilds;
+package netneutrality.hooks.guilds;
/*
* Copyright (c) anthorob
diff --git a/src/main/java/netneutrality/handler/hooks/message/EditHandler.java b/src/main/java/netneutrality/hooks/message/EditHandler.java
similarity index 97%
rename from src/main/java/netneutrality/handler/hooks/message/EditHandler.java
rename to src/main/java/netneutrality/hooks/message/EditHandler.java
index 03cc806..4637c14 100644
--- a/src/main/java/netneutrality/handler/hooks/message/EditHandler.java
+++ b/src/main/java/netneutrality/hooks/message/EditHandler.java
@@ -1,4 +1,4 @@
-package netneutrality.handler.hooks.message;
+package netneutrality.hooks.message;
/*
* Copyright (c) anthorob
diff --git a/src/main/java/netneutrality/handler/hooks/message/MessageReceivedHandler.java b/src/main/java/netneutrality/hooks/message/MessageReceivedHandler.java
similarity index 65%
rename from src/main/java/netneutrality/handler/hooks/message/MessageReceivedHandler.java
rename to src/main/java/netneutrality/hooks/message/MessageReceivedHandler.java
index 62bb276..9946879 100644
--- a/src/main/java/netneutrality/handler/hooks/message/MessageReceivedHandler.java
+++ b/src/main/java/netneutrality/hooks/message/MessageReceivedHandler.java
@@ -1,4 +1,4 @@
-package netneutrality.handler.hooks.message;
+package netneutrality.hooks.message;
/*
* Copyright (c) anthorob
*
@@ -8,39 +8,42 @@ package netneutrality.handler.hooks.message;
import io.sentry.Breadcrumb;
import io.sentry.Sentry;
-import net.dv8tion.jda.api.entities.*;
-import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
+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 net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import netneutrality.command.AbstractCommand;
import netneutrality.core.CommandManager;
import netneutrality.core.GuildManager;
-import netneutrality.core.context.CommandContext;
-import netneutrality.db.GSettings;
+import netneutrality.core.context.MessageCommandContext;
import netneutrality.utils.Settings;
import org.jetbrains.annotations.NotNull;
public class MessageReceivedHandler extends ListenerAdapter {
@Override
- public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
+ public void onMessageReceived(@NotNull MessageReceivedEvent event) {
if (event.getAuthor().isBot()) return;
if (event.isWebhookMessage()) return;
+ if (!event.isFromGuild())
+ return;
+
Message message = event.getMessage();
Member member = event.getMember();
Guild guild = event.getGuild();
- TextChannel channel = event.getChannel();
+ TextChannel channel = (TextChannel) event.getChannel();
Sentry.addBreadcrumb(Breadcrumb.info("New message from " + member.getEffectiveName()));
- CommandContext context = CommandContext.createContext(event);
+ MessageCommandContext context = MessageCommandContext.createContext(event);
- GuildManager.getManager(guild).getRateLimiter().check(member, message, channel);
GuildManager.getManager(guild).checkAndLogMessage(message, member, channel);
String rawMessage = message.getContentDisplay().trim();
- //String prefix = Settings.getInstance().get("BOT_PREFIX", "$");
- String prefix = GuildManager.getManager(guild).getSetting(GSettings.PREFIX);
+ String prefix = Settings.getInstance().get("BOT_PREFIX", "$");
if (rawMessage.startsWith(prefix)) {
rawMessage = rawMessage.replaceFirst(String.format("^[%s\\s]{1,}", prefix), "").trim();
@@ -54,8 +57,6 @@ public class MessageReceivedHandler extends ListenerAdapter {
context.dispatch(command);
}
- } else {
- GuildManager.getManager(guild).checkBlacklist(message, channel);
}
}
}
diff --git a/src/main/java/netneutrality/hooks/message/ReactionHandler.java b/src/main/java/netneutrality/hooks/message/ReactionHandler.java
new file mode 100644
index 0000000..abcf8b2
--- /dev/null
+++ b/src/main/java/netneutrality/hooks/message/ReactionHandler.java
@@ -0,0 +1,32 @@
+package netneutrality.hooks.message;
+/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.events.message.MessageUpdateEvent;
+import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
+import net.dv8tion.jda.api.events.message.react.MessageReactionRemoveEvent;
+import net.dv8tion.jda.api.hooks.ListenerAdapter;
+import org.jetbrains.annotations.NotNull;
+
+public class ReactionHandler extends ListenerAdapter {
+
+ @Override
+ public void onMessageReactionAdd(@NotNull MessageReactionAddEvent event) {
+ Member member = event.getMember();
+ }
+
+ @Override
+ public void onMessageReactionRemove(@NotNull MessageReactionRemoveEvent event) {
+
+ }
+
+ @Override
+ public void onMessageUpdate(@NotNull MessageUpdateEvent event) {
+
+ }
+}
diff --git a/src/main/java/netneutrality/handler/hooks/voice/VoiceEventHandler.java b/src/main/java/netneutrality/hooks/voice/VoiceEventHandler.java
similarity index 95%
rename from src/main/java/netneutrality/handler/hooks/voice/VoiceEventHandler.java
rename to src/main/java/netneutrality/hooks/voice/VoiceEventHandler.java
index 7a42370..3bc75c3 100644
--- a/src/main/java/netneutrality/handler/hooks/voice/VoiceEventHandler.java
+++ b/src/main/java/netneutrality/hooks/voice/VoiceEventHandler.java
@@ -1,4 +1,4 @@
-package netneutrality.handler.hooks.voice;
+package netneutrality.hooks.voice;
/*
* Copyright (c) anthorob
*
diff --git a/src/main/java/netneutrality/http/server/WebApi.java b/src/main/java/netneutrality/http/server/WebApi.java
index ccb21d3..8a01775 100644
--- a/src/main/java/netneutrality/http/server/WebApi.java
+++ b/src/main/java/netneutrality/http/server/WebApi.java
@@ -13,7 +13,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
-import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
diff --git a/src/main/java/netneutrality/music/MusicManager.java b/src/main/java/netneutrality/music/MusicManager.java
index de0ea5e..f0f3b8f 100644
--- a/src/main/java/netneutrality/music/MusicManager.java
+++ b/src/main/java/netneutrality/music/MusicManager.java
@@ -10,7 +10,6 @@ package netneutrality.music;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
-import com.sedmelluq.discord.lavaplayer.source.AudioSourceManager;
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager;
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioSourceManager;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
@@ -21,6 +20,7 @@ import net.dv8tion.jda.api.entities.VoiceChannel;
import netneutrality.core.GuildManager;
import netneutrality.core.LogHandler;
import netneutrality.core.context.CommandContext;
+import netneutrality.core.context.SlashCommandContext;
import netneutrality.db.GSettings;
import netneutrality.exceptions.CommandExecutionException;
import netneutrality.music.loadable.LoadableSong;
@@ -30,7 +30,9 @@ import netneutrality.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
@@ -43,7 +45,6 @@ public class MusicManager {
private final static ScheduledExecutorService executor = (ScheduledExecutorService) ThreadManager.getExecutor("music", ThreadManager.ExecutorType.SCHEDULED);
private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
- private final static Map sources = new HashMap<>();
private final Guild guild;
private final AudioPlayer player;
private final TrackScheduler scheduler;
@@ -75,12 +76,9 @@ public class MusicManager {
YoutubeAudioSourceManager youtubeSource = new YoutubeAudioSourceManager(true,
Settings.getInstance().get("GG_EMAIL", ""),
Settings.getInstance().get("GG_PASS", ""));
- SoundCloudAudioSourceManager soundcloudSource = SoundCloudAudioSourceManager.createDefault();
- sources.put("youtube", youtubeSource);
- sources.put("soundcloud", soundcloudSource);
playerManager.registerSourceManager(youtubeSource);
- playerManager.registerSourceManager(soundcloudSource);
+ playerManager.registerSourceManager(SoundCloudAudioSourceManager.createDefault());
}
public boolean isNotConnectedTo(VoiceChannel vChannel) {
@@ -115,7 +113,7 @@ public class MusicManager {
}
public synchronized Member getRequesterOfCurrentTrack() {
- QueueManager.TrackInfo info = scheduler.getQueueManager().getQueue().peek();
+ QueueManager.TrackInfo info = scheduler.getQueueManager().peekHeadOfQueue();
if (info == null)
return null;
@@ -152,9 +150,8 @@ public class MusicManager {
public static void disconnectPlayers() {
for (MusicManager mm : managers.values()) {
- mm.leave();
+ mm.getScheduler().getQueueManager().clearQueue();
mm.player.destroy();
- mm.scheduler.getQueueManager().getQueue().clear();
}
}
@@ -175,7 +172,7 @@ public class MusicManager {
public void play(List songs, CommandContext context, boolean needToBeConnected, boolean silent) {
Member member = context.getGuildUser();
- TextChannel channel = context.getChannel();
+ TextChannel channel = (TextChannel) context.getChannel();
if (member.getVoiceState() == null) {
logger.error("Guild {}: Voice state is null", guild.getId());
@@ -185,12 +182,12 @@ public class MusicManager {
return;
}
- if (!member.getVoiceState().inVoiceChannel()) {
+ if (!member.getVoiceState().inAudioChannel()) {
context.replyToMessage("You are not in a voice channel");
return;
}
- VoiceChannel vChannel = member.getVoiceState().getChannel();
+ VoiceChannel vChannel = (VoiceChannel) member.getVoiceState().getChannel();
if (needToBeConnected && isNotConnectedTo(vChannel)) {
context.replyToMessage("The player is not in your voice channel");
return;
@@ -215,23 +212,9 @@ public class MusicManager {
player.stopTrack();
}
- public synchronized void skip(int nbTrack) {
- if (!scheduler.getQueueManager().getQueue().isEmpty()) {
- if (nbTrack >= scheduler.getQueueManager().getQueue().size()) {
- nbTrack = 1;
- }
-
- logger.debug("Guild {}: skipping tracks, toSkip={}", guild.getId(), nbTrack);
- scheduler.getQueueManager().skipAndPlay(nbTrack);
- } else {
- leave();
- }
- }
-
public synchronized void voteSkip(CommandContext context) {
- Queue queue = scheduler.getQueueManager().getQueue();
- VoiceChannel voiceChannel = guild.getAudioManager().getConnectedChannel();
- QueueManager.TrackInfo info = queue.peek();
+ VoiceChannel voiceChannel = (VoiceChannel) guild.getAudioManager().getConnectedChannel();
+ QueueManager.TrackInfo info = scheduler.getQueueManager().peekHeadOfQueue();
if (!isCurrentlyPlaying() || voiceChannel == null) {
return;
@@ -246,7 +229,7 @@ public class MusicManager {
if (connected < 3) {
context.reply("Skipping current track since not enough people are connected to the voice channel.");
- skip(1);
+ scheduler.getQueueManager().skip(1);
return;
}
@@ -258,7 +241,7 @@ public class MusicManager {
if (info.getSkips().size() > needed) {
context.reply("Skipping current track: %s", info.getTrack().getInfo().title);
- skip(1);
+ scheduler.getQueueManager().skip(1);
} else {
context.reply("Adding your vote to skip the current track. Current votes: %d/%d", info.getSkips().size(), (int) Math.ceil(needed));
}
@@ -269,14 +252,10 @@ public class MusicManager {
}
public int getQueueSize() {
- synchronized (scheduler.getQueueManager().getQueue()) {
- return scheduler.getQueueManager().getQueue().size();
- }
-
+ return scheduler.getQueueManager().getQueueSize();
}
public TrackScheduler getScheduler() {
return scheduler;
}
-
}
diff --git a/src/main/java/netneutrality/music/QueueManager.java b/src/main/java/netneutrality/music/QueueManager.java
index 550449f..b2f4518 100644
--- a/src/main/java/netneutrality/music/QueueManager.java
+++ b/src/main/java/netneutrality/music/QueueManager.java
@@ -14,10 +14,11 @@ import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.LinkedBlockingDeque;
+import java.util.function.Predicate;
public class QueueManager {
- static class TrackInfo {
+ public static class TrackInfo {
private final AudioTrack track;
private final Member member;
@@ -101,9 +102,9 @@ public class QueueManager {
this.queue = new LinkedBlockingDeque<>();
}
- public Queue getQueue() {
+ public List getQueue() {
synchronized (queue) {
- return queue;
+ return queue.stream().toList();
}
}
@@ -115,15 +116,65 @@ public class QueueManager {
return guild;
}
+ public int getQueueSize() {
+ synchronized (queue) {
+ return queue.size();
+ }
+ }
+
+ public List getQueueWithFilter(Predicate super TrackInfo> filter) {
+ synchronized (queue) {
+ return queue.stream().filter(filter).toList();
+ }
+ }
+
+ public TrackInfo peekHeadOfQueue() {
+ synchronized (queue) {
+ return queue.peek();
+ }
+ }
+
+ public TrackInfo pollHeadOfQueue() {
+ synchronized (queue) {
+ return queue.poll();
+ }
+ }
+
+ public boolean isEmpty() {
+ synchronized (queue) {
+ return queue.isEmpty();
+ }
+ }
+
public void clearQueue() {
- scheduler.getMusicManager().leave();
scheduler.getMusicManager().stopLoading();
+ scheduler.getMusicManager().leave();
synchronized (queue) {
queue.clear();
}
}
+ public void removeTracksFromUser(Member member) {
+ synchronized (queue) {
+ int size = queue.stream().filter(trackInfo -> member.equals(trackInfo.getRequester())).toList().size();
+
+ if (size > 0) {
+ if (size == queue.size()) {
+ clearQueue();
+ return;
+ }
+
+ TrackInfo first = queue.peek();
+ queue.removeIf(trackInfo -> member.equals(trackInfo.getRequester()));
+
+ if (first != null && member.equals(first.getRequester())) {
+ skip(1);
+ }
+ }
+ }
+ }
+
public ArrayList getAllQueuedTrack() {
synchronized (queue) {
ArrayList tracks = new ArrayList<>();
@@ -156,7 +207,7 @@ public class QueueManager {
}
}
- public void nextTrack(AudioPlayer player) {
+ public void playNextTrack(AudioPlayer player) {
synchronized (queue) {
TrackInfo last = queue.poll();
TrackInfo next = queue.peek();
@@ -164,7 +215,7 @@ public class QueueManager {
if (next != null) {
if (last != null && last.getTrack().equals(next.getTrack())) {
logger.debug("Guild {}: duplicate track in queue found, skipping to next. last={}, next={}", guild.getId(), last.getTrack().getIdentifier(), next.getTrack().getIdentifier());
- nextTrack(player);
+ playNextTrack(player);
} else {
player.startTrack(next.getTrack(), false);
}
@@ -175,12 +226,23 @@ public class QueueManager {
}
- public void skipAndPlay(int nb) {
- if (nb == 0)
+ public void skip(int nbTrack) {
+ if (nbTrack == 0)
return;
synchronized (queue) {
- for (int i = 0; i < nb; i++) {
+
+ if (queue.isEmpty()) {
+ scheduler.getMusicManager().leave();
+ return;
+ }
+
+ if (nbTrack > queue.size()) {
+ nbTrack = 1;
+ }
+
+ logger.debug("Guild {}: skipping tracks, toSkip={}", guild.getId(), nbTrack);
+ for (int i = 0; i < nbTrack; i++) {
TrackInfo last = queue.poll();
}
@@ -190,8 +252,8 @@ public class QueueManager {
} else {
player.stopTrack();
}
- }
+ }
}
public void shuffle() {
@@ -212,17 +274,17 @@ public class QueueManager {
}
}
- protected boolean removeFromQueue(int index) {
+ public boolean removeFromQueue(int index) {
synchronized (queue) {
if (queue.size() > 0 && index <= queue.size()) {
logger.debug("Guild {}: removing index {} from queue", guild.getId(), index - 1);
if (index == 1) {
- skipAndPlay(1);
+ skip(1);
return true;
}
- ArrayList newQueue = new ArrayList<>(queue);
+ List newQueue = new ArrayList<>(queue);
newQueue.remove(index - 1);
queue.clear();
diff --git a/src/main/java/netneutrality/music/TrackLoadingHandler.java b/src/main/java/netneutrality/music/TrackLoadingHandler.java
index 6d7f853..b61c956 100644
--- a/src/main/java/netneutrality/music/TrackLoadingHandler.java
+++ b/src/main/java/netneutrality/music/TrackLoadingHandler.java
@@ -30,7 +30,7 @@ public class TrackLoadingHandler implements AudioLoadResultHandler {
private boolean loadingDisabled = false;
private final Guild guild;
private final TrackScheduler scheduler;
- private final CommandContext context;
+ private final CommandContext context;
public TrackLoadingHandler(CommandContext context, MusicManager manager, String identifier, SourceFinder.AudioSourceType type, boolean silent) {
this.identifier = identifier;
@@ -66,8 +66,7 @@ public class TrackLoadingHandler implements AudioLoadResultHandler {
scheduler.getQueueManager().queue(audioTrack, context.getGuildUser());
if (!silent) {
- scheduler.sendMessageToChannel(MessageFunction.buildAddingTrackMessage(audioTrack, context.getGuildUser(), type));
- // context.reply(MessageFunction.buildAddingTrackMessage(audioTrack, context.getGuildUser(), type));
+ context.reply(MessageFunction.buildAddingTrackMessage(audioTrack, type));
}
}
@@ -88,8 +87,7 @@ public class TrackLoadingHandler implements AudioLoadResultHandler {
scheduler.getQueueManager().queue(track, context.getGuildUser());
if (!silent) {
- scheduler.sendMessageToChannel(MessageFunction.buildAddingTrackMessage(track, context.getGuildUser(), type));
- // context.reply(MessageFunction.buildAddingTrackMessage(track, context.getGuildUser(), type));
+ context.reply(MessageFunction.buildAddingTrackMessage(track, type));
}
return;
@@ -97,8 +95,7 @@ public class TrackLoadingHandler implements AudioLoadResultHandler {
context.deleteMessage();
if (!silent) {
- scheduler.sendMessageToChannel(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, context.getGuildUser(), identifier, type));
- // context.reply(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, context.getGuildUser(), identifier, type));
+ context.reply(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, identifier, type));
}
for (AudioTrack track : audioPlaylist.getTracks()) {
@@ -106,9 +103,7 @@ public class TrackLoadingHandler implements AudioLoadResultHandler {
break;
}
- synchronized (scheduler.getQueueManager().getQueue()) {
- scheduler.getQueueManager().queue(track, context.getGuildUser());
- }
+ scheduler.getQueueManager().queue(track, context.getGuildUser());
}
}
}
diff --git a/src/main/java/netneutrality/music/TrackScheduler.java b/src/main/java/netneutrality/music/TrackScheduler.java
index da3031b..dad5daf 100644
--- a/src/main/java/netneutrality/music/TrackScheduler.java
+++ b/src/main/java/netneutrality/music/TrackScheduler.java
@@ -99,13 +99,11 @@ public class TrackScheduler extends AudioEventAdapter {
// check if mayStartNext
if (endReason == AudioTrackEndReason.FINISHED || endReason == AudioTrackEndReason.LOAD_FAILED) {
- queueManager.nextTrack(player);
+ queueManager.playNextTrack(player);
}
if (endReason == AudioTrackEndReason.STOPPED) {
- synchronized (queueManager.getQueue()) {
- queueManager.getQueue().poll();
- }
+ queueManager.pollHeadOfQueue();
}
// endReason == FINISHED: A track finished or died by an exception (mayStartNext = true).
@@ -127,6 +125,6 @@ public class TrackScheduler extends AudioEventAdapter {
public void onTrackStuck(AudioPlayer player, AudioTrack track, long thresholdMs) {
logger.debug("Guild {}: currently playing track is stuck: {}", guild.getId(), track.getIdentifier());
sendMessageToChannel("Current track is stuck, skipping to next");
- queueManager.nextTrack(player);
+ queueManager.playNextTrack(player);
}
}
diff --git a/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java b/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java
index 2a22301..f24a2e6 100644
--- a/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java
+++ b/src/main/java/netneutrality/thread/MusicPlayerAutoDisconnectThread.java
@@ -25,12 +25,12 @@ public class MusicPlayerAutoDisconnectThread implements Runnable {
@Override
public void run() {
Guild guild = manager.getGuild();
- VoiceChannel channel = guild.getAudioManager().getConnectedChannel();
+ VoiceChannel channel = (VoiceChannel) guild.getAudioManager().getConnectedChannel();
if (channel != null) {
List members = channel.getMembers().stream().filter(member -> !member.getId().equals(NetNeutrality.getSelf().getId())).toList();
- if (members.size() == 0 || manager.getScheduler().getQueueManager().getQueue().isEmpty()) {
+ if (members.size() == 0 || manager.getScheduler().getQueueManager().isEmpty()) {
LoggerFactory.getLogger(MusicPlayerAutoDisconnectThread.class).debug("Guild {}: auto-disconnect player from voice channel: {}", guild.getId(), channel.getId());
manager.leave();
}
diff --git a/src/main/java/netneutrality/utils/ChannelFunction.java b/src/main/java/netneutrality/utils/ChannelFunction.java
deleted file mode 100644
index abe112f..0000000
--- a/src/main/java/netneutrality/utils/ChannelFunction.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package netneutrality.utils;
-
-import io.sentry.ISpan;
-import io.sentry.ITransaction;
-import io.sentry.Sentry;
-import io.sentry.SpanStatus;
-import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.entities.TextChannel;
-import netneutrality.thread.ThreadManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.time.OffsetDateTime;
-import java.util.List;
-
-public class ChannelFunction {
-
- private static final Logger logger = LoggerFactory.getLogger(ChannelFunction.class);
-
- public static void bulkDeleteMessage(TextChannel channel, int toDelete) {
-
- if (toDelete >= 2500) return;
-
- ThreadManager.getExecutor("bulk-delete", ThreadManager.ExecutorType.FIXED).submit(() -> {
- ITransaction transaction = Sentry.startTransaction(String.format("bulkDeleteMessage(%s, %d)", channel.getId(), toDelete), "task");
- transaction.setData("channel", channel.getId());
- transaction.setData("toDelete", toDelete);
- transaction.setTag("operation", "bulk-delete");
-
- try {
-
- int toDeleteFinal = toDelete + 1;
- int iteration = toDeleteFinal / 100;
- for (int i = 0; i < iteration; i++) {
- ISpan innerSpan = transaction.startChild("task", "Processing iteration " + (i + 1) + "/" + iteration);
- try {
- List messages = channel.getHistory().retrievePast(100).complete();
- deleteFromList(messages, channel, innerSpan);
- toDeleteFinal -= 100;
- innerSpan.setStatus(SpanStatus.OK);
- } catch (Exception e) {
- innerSpan.setThrowable(e);
- innerSpan.setStatus(SpanStatus.INTERNAL_ERROR);
- throw e;
- } finally {
- innerSpan.finish();
- }
- }
-
- if (toDeleteFinal > 0) {
- ISpan innerSpan = transaction.startChild("task", String.format("Processing final iteration (%d messages)", toDeleteFinal));
- try {
- List messages = channel.getHistory().retrievePast(toDeleteFinal).complete();
- deleteFromList(messages, channel, innerSpan);
- innerSpan.setStatus(SpanStatus.OK);
- } catch (Exception e) {
- innerSpan.setThrowable(e);
- innerSpan.setStatus(SpanStatus.INTERNAL_ERROR);
- throw e;
- } finally {
- innerSpan.finish();
- }
-
-
- innerSpan.finish();
- }
-
- transaction.setStatus(SpanStatus.OK);
- } catch (Exception e) {
- transaction.setThrowable(e);
- transaction.setStatus(SpanStatus.INTERNAL_ERROR);
- } finally {
- transaction.finish();
- }
- });
- }
-
- private synchronized static void deleteFromList(List messages, TextChannel channel, ISpan span) {
- ISpan innerSpan = span.startChild("delete", "Executing delete of: " + messages.size() + " messages");
- try {
- channel.deleteMessages(messages).complete();
- innerSpan.setStatus(SpanStatus.OK);
- } catch (IllegalArgumentException e) {
- innerSpan.setThrowable(e);
- innerSpan.setStatus(SpanStatus.OUT_OF_RANGE);
- messages.forEach(m -> {
- if (!m.getTimeCreated().isBefore(OffsetDateTime.now().minusWeeks(2))) {
- m.delete().queue();
- }
- });
- } finally {
- innerSpan.finish();
- }
- }
-}
diff --git a/src/main/java/netneutrality/utils/ChannelMessagePurger.java b/src/main/java/netneutrality/utils/ChannelMessagePurger.java
new file mode 100644
index 0000000..2cdd5ee
--- /dev/null
+++ b/src/main/java/netneutrality/utils/ChannelMessagePurger.java
@@ -0,0 +1,171 @@
+package netneutrality.utils;
+/*
+ * Copyright (c) anthorob
+ *
+ * https://xtremcommunity.com/
+ * https://discord.gg/CdFcyQ
+ */
+
+import io.sentry.ISpan;
+import io.sentry.ITransaction;
+import io.sentry.Sentry;
+import io.sentry.SpanStatus;
+import net.dv8tion.jda.api.entities.GuildMessageChannel;
+import net.dv8tion.jda.api.entities.Message;
+import net.dv8tion.jda.api.entities.MessageHistory;
+import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
+import netneutrality.core.context.CommandContext;
+import netneutrality.thread.ThreadManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class ChannelMessagePurger {
+
+ private static final Logger logger = LoggerFactory.getLogger(ChannelMessagePurger.class);
+ private static final Map instances = new HashMap<>();
+ private final GuildMessageChannel channel;
+ private final Lock lock;
+
+ private ChannelMessagePurger(GuildMessageChannel channel) {
+ this.channel = channel;
+ this.lock = new ReentrantLock();
+ }
+
+ public static ChannelMessagePurger getPurger(GuildMessageChannel channel) {
+ return instances.computeIfAbsent(channel, ChannelMessagePurger::new);
+ }
+
+ public boolean canLockBeAcquired() {
+ boolean acquired = lock.tryLock();
+ if (acquired)
+ lock.unlock();
+
+ return acquired;
+ }
+
+ public void purgeMessages(CommandContext context, int toPurge) {
+ ThreadManager.getExecutor("bulk-delete", ThreadManager.ExecutorType.FIXED).submit(() -> {
+ if (lock.tryLock()) {
+ try {
+ int total = countAllChannelMessages(channel);
+ int finalToPurge = toPurge;
+
+ if (finalToPurge > total) {
+ finalToPurge = total;
+ }
+
+ safePurge(context, finalToPurge);
+ } finally {
+ lock.unlock();
+ }
+ }
+ });
+ }
+
+ public void purgeChannel(CommandContext context) {
+ ThreadManager.getExecutor("bulk-delete", ThreadManager.ExecutorType.FIXED).submit(() -> {
+ if (lock.tryLock()) {
+ try {
+ int total = countAllChannelMessages(channel);
+ context.reply("Number of messages to purge: %d", total);
+
+ safePurge(context, total);
+ } finally {
+ lock.unlock();
+ }
+ }
+ });
+ }
+
+ private synchronized int countAllChannelMessages(GuildMessageChannel channel) {
+ logger.info("Guild {}: counting all messages from channel {}", channel.getGuild().getId(), channel.getId());
+ MessageHistory history = channel.getHistory();
+ int totalCount = 0;
+ int iterationCount = 0;
+
+ while (totalCount == iterationCount) {
+ history.retrievePast(100).complete();
+
+ iterationCount += 100;
+ totalCount = history.size();
+ }
+ logger.info("Guild {}: Counted {} messages from channel {}", channel.getGuild().getId(), totalCount, channel.getId());
+
+ return totalCount;
+ }
+
+ private synchronized void safePurge(CommandContext context, int toPurge) {
+ ITransaction transaction = Sentry.startTransaction(String.format("purge messages from guild %s)", channel.getGuild().getId()), "task");
+ transaction.setData("channel", channel.getId());
+ transaction.setData("toPurge", toPurge);
+
+ if (toPurge == 1) {
+ toPurge += 1;
+ }
+
+ int tracker = toPurge;
+ int iteration = tracker / 100;
+ boolean olderThan2Weeks = false;
+ context.replyToMessage("Purging iterations to do: %d", iteration);
+
+ try {
+ for (int i = 0; i < iteration; i++) {
+ ISpan innerSpan = transaction.startChild("retrieve-messages", "Processing iteration " + (i + 1) + "/" + iteration);
+ try {
+ List messages = channel.getHistory().retrievePast(100).complete();
+ channel.deleteMessages(messages).complete();
+ tracker -= 100;
+ innerSpan.setStatus(SpanStatus.OK);
+ } catch (IllegalArgumentException ex) {
+ olderThan2Weeks = true;
+ } catch (Exception e) {
+ innerSpan.setThrowable(e);
+ innerSpan.setStatus(SpanStatus.INTERNAL_ERROR);
+ } finally {
+ innerSpan.finish();
+ }
+ }
+
+ if (tracker > 0) {
+ ISpan innerSpan = transaction.startChild("retrieve-messages", String.format("Processing final iteration (%d messages)", tracker));
+ try {
+ List messages = channel.getHistory().retrievePast(tracker).complete();
+ channel.deleteMessages(messages).complete();
+ innerSpan.setStatus(SpanStatus.OK);
+ } catch (IllegalArgumentException ex) {
+ olderThan2Weeks = true;
+ } catch (Exception e) {
+ innerSpan.setThrowable(e);
+ innerSpan.setStatus(SpanStatus.INTERNAL_ERROR);
+ } finally {
+ innerSpan.finish();
+ }
+
+
+ innerSpan.finish();
+ }
+
+ } catch (Exception e) {
+ transaction.setThrowable(e);
+ transaction.setStatus(SpanStatus.INTERNAL_ERROR);
+ } finally {
+ transaction.finish();
+ MessageCreateBuilder builder = new MessageCreateBuilder()
+ .addContent("Finished purging ")
+ .addContent(String.valueOf(toPurge))
+ .addContent(" messages.");
+
+ if (olderThan2Weeks) {
+ builder.addContent("\n").addContent("Messages older than two weeks weren't deleted.");
+ }
+ context.reply(builder.build());
+ lock.unlock();
+ }
+ }
+}
diff --git a/src/main/java/netneutrality/utils/MessageFunction.java b/src/main/java/netneutrality/utils/MessageFunction.java
index a6069ca..8fbca70 100644
--- a/src/main/java/netneutrality/utils/MessageFunction.java
+++ b/src/main/java/netneutrality/utils/MessageFunction.java
@@ -14,20 +14,22 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.*;
import netneutrality.command.AbstractCommand;
import netneutrality.command.CommandType;
+import netneutrality.core.CommandManager;
import netneutrality.core.context.CommandContext;
import netneutrality.exceptions.CommandException;
-import netneutrality.exceptions.CommandExecutionException;
import netneutrality.music.MusicManager;
+import netneutrality.music.QueueManager;
import netneutrality.music.SourceFinder;
-import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DurationFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.*;
import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
-import java.util.*;
+import java.util.Set;
public class MessageFunction {
@@ -35,7 +37,7 @@ public class MessageFunction {
public static Member getStartingMention(Message message) {
if (isStartingWithMention(message)) {
- return message.getMentionedMembers().get(0);
+ return message.getMentions().getMembers().get(0);
}
return null;
@@ -45,7 +47,7 @@ public class MessageFunction {
if (!message.isFromType(ChannelType.TEXT))
return false;
- List mentions = message.getMentionedMembers();
+ List mentions = message.getMentions().getMembers();
for (Member member : mentions) {
if (message.getContentDisplay().startsWith("@" + member.getUser().getName()))
@@ -55,9 +57,8 @@ public class MessageFunction {
return false;
}
- public static MessageEmbed buildCurrentlyPlayingMessage(MusicManager manager, Member user) {
+ public static MessageEmbed buildCurrentlyPlayingMessage(MusicManager manager) {
AudioTrack current = manager.getCurrentlyPlaying();
- Member requester = (manager.getRequesterOfCurrentTrack() == null ? user : manager.getRequesterOfCurrentTrack());
EmbedBuilder message = new EmbedBuilder();
message.setAuthor("Link to track", String.format("https://youtu.be/%s", current.getIdentifier()));
@@ -66,15 +67,13 @@ public class MessageFunction {
message.setColor(Color.BLUE);
message.addField("Track title: ", current.getInfo().title, false);
message.addField("Duration: ", DurationFormatUtils.formatDuration(current.getPosition(), "**HH:mm:ss**", true) + " / " + DurationFormatUtils.formatDuration(current.getDuration(), "**HH:mm:ss**", true), false);
- message.setFooter("Requested by " + requester.getEffectiveName(), requester.getAvatarUrl());
message.setTimestamp(OffsetDateTime.now());
return message.build();
}
- public static MessageEmbed buildAddingTrackMessage(AudioTrack track, Member member, SourceFinder.AudioSourceType type) {
+ public static MessageEmbed buildAddingTrackMessage(AudioTrack track, SourceFinder.AudioSourceType type) {
EmbedBuilder message = new EmbedBuilder();
- String avatarUrl = StringUtils.isEmpty(member.getAvatarUrl()) ? member.getUser().getAvatarUrl() : member.getAvatarUrl();
String url = track.getIdentifier();
String thumbnail = null;
@@ -90,15 +89,13 @@ public class MessageFunction {
message.setColor(Color.BLUE);
message.addField("Track title: ", String.format("[**`%s`**](%s)", track.getInfo().title, url), false);
message.addField("Duration: ", DurationFormatUtils.formatDuration(track.getDuration(), "**HH:mm:ss**", true), false);
- message.setFooter("Requested by " + member.getEffectiveName(), avatarUrl);
message.setTimestamp(OffsetDateTime.now());
return message.build();
}
- public static MessageEmbed buildAddingPlaylistMessage(AudioPlaylist playlist, Member member, String identifier, SourceFinder.AudioSourceType type) {
+ public static MessageEmbed buildAddingPlaylistMessage(AudioPlaylist playlist, String identifier, SourceFinder.AudioSourceType type) {
EmbedBuilder message = new EmbedBuilder();
- String avatarUrl = StringUtils.isEmpty(member.getAvatarUrl()) ? member.getUser().getAvatarUrl() : member.getAvatarUrl();
String url = identifier;
String thumbnail = null;
@@ -114,14 +111,12 @@ public class MessageFunction {
message.setColor(Color.BLUE);
message.addField("Playlist: ", String.format("[**`%s`**](%s)", playlist.getName(), url), false);
message.addField("Number of tracks: ", String.valueOf(playlist.getTracks().size()), false);
- message.setFooter("Requested by " + member.getEffectiveName(), avatarUrl);
message.setTimestamp(OffsetDateTime.now());
return message.build();
}
- public static MessageEmbed buildViewQueueMessage(MusicManager manager, Member member, boolean currentlyPlaying) {
- String avatarUrl = StringUtils.isEmpty(member.getAvatarUrl()) ? member.getUser().getAvatarUrl() : member.getAvatarUrl();
+ public static MessageEmbed buildViewQueueMessage(MusicManager manager, boolean currentlyPlaying) {
ArrayList tracks = manager.getScheduler().getQueueManager().getAllQueuedTrack();
AudioTrack current = manager.getCurrentlyPlaying();
int numberofTracksShown = Math.min(tracks.size(), 10);
@@ -143,56 +138,55 @@ public class MessageFunction {
if (index == 10) break;
}
- message.setFooter("Requested by " + member.getEffectiveName(), avatarUrl);
message.setTimestamp(OffsetDateTime.now());
return message.build();
}
- public static MessageEmbed buildHelpMessage(AbstractCommand command) {
+ public static MessageEmbed buildUserTracksMessage(MusicManager manager, Member member) {
+ List tracks = manager.getScheduler()
+ .getQueueManager()
+ .getQueueWithFilter(trackInfo -> member.equals(trackInfo.getRequester()));
+ AudioTrack current = manager.getCurrentlyPlaying();
+ int numberofTracksShown = Math.min(tracks.size(), 10);
+
EmbedBuilder message = new EmbedBuilder();
- message.setTitle(":information_source: Help for command " + command.getCommandName());
+ message.setTitle(String.format("Tracks added by %s (showing %d out of %d items):", member.getAsMention(), numberofTracksShown, tracks.size()));
message.setColor(Color.BLUE);
- message.addField("Command", command.getCommandName(), false);
- message.addField("Description", command.getDescription(), false);
- message.addField("Aliases", ((command.getAlias() == null || command.getAlias().length == 0) ? "None" : Arrays.toString(command.getAlias()).replaceAll("[\\[\\]]", "")), false);
- message.addField("Usage", (command.getUsage() == null ? "No arguments defined" : command.getUsage().toString()), false);
+
+ int index = 0;
+ for (QueueManager.TrackInfo track : tracks) {
+ AudioTrackInfo info = track.getTrack().getInfo();
+
+ if (current != null && current.getInfo().title.equals(info.title)) {
+ message.addField("Track #" + ++index + " (Currently playing)", info.title, false);
+ } else {
+ message.addField("Track #" + ++index, info.title, false);
+ }
+
+ if (index == 10) break;
+ }
+ message.setTimestamp(OffsetDateTime.now());
return message.build();
}
- public static ArrayList buildHelpMessage(HashMap commands, boolean admin) {
-
- SortedSet keys = new TreeSet<>(commands.keySet());
+ public static ArrayList buildHelpMessage(Member member) {
HashMap help = new HashMap<>();
- for (String commandName : keys) {
- AbstractCommand command = commands.get(commandName);
+ for (AbstractCommand command : CommandManager.commands.values()) {
if (command.getType() == null)
continue;
String description = "No description yet";
- StringBuilder availAlias = new StringBuilder();
if (command.isEnabled() && command.getType() != CommandType.UNLISTED) {
- if (command.getType() == CommandType.ADMINISTRATION && !admin)
+ if (command.getType() == CommandType.ADMINISTRATION && !UserFunction.isAdmin(member))
continue;
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());
@@ -205,9 +199,8 @@ public class MessageFunction {
message.setColor(Color.BLUE);
}
- message.addField(String.format("%s %s", command.getCommandName(), availAlias), description, false);
+ message.addField(String.format("%s", command.getCommandName()), description, false);
}
-
}
ArrayList messages = new ArrayList<>();
diff --git a/src/main/java/netneutrality/utils/MusicUtils.java b/src/main/java/netneutrality/utils/MusicUtils.java
index a4caf74..dbee39b 100644
--- a/src/main/java/netneutrality/utils/MusicUtils.java
+++ b/src/main/java/netneutrality/utils/MusicUtils.java
@@ -16,10 +16,11 @@ public class MusicUtils {
public static boolean checkIfConnected(MusicManager manager, CommandContext context) {
if (context.getGuildUser().getVoiceState() == null) {
+ context.reply("Voice state is null, this should not happen");
throw new CommandExecutionException("Voice state is null, this should not happen", context, null);
}
- if (!context.getGuildUser().getVoiceState().inVoiceChannel()) {
+ if (!context.getGuildUser().getVoiceState().inAudioChannel()) {
context.reply("You are not in a voice channel");
return false;
}
@@ -29,7 +30,7 @@ public class MusicUtils {
return false;
}
- VoiceChannel vChannel = context.getGuildUser().getVoiceState().getChannel();
+ VoiceChannel vChannel = (VoiceChannel) context.getGuildUser().getVoiceState().getChannel();
if (manager.isNotConnectedTo(vChannel)) {
context.reply("The bot isn't in your voice channel");
return false;