Create abstraction to combine slash commands and message commands
Usage and options checking (arguments count, type checking) Options parsing for message commands (both types of commands are now registered like slash commands and the abstraction will handle the parsing of all options as if it was a slash command) Refactor of the help command for better readability and more helpful text, which is now based on the available options of a command
This commit is contained in:
1 parent
4c27b80527
commit
2afab8f1f5
51 files changed
+1440
-689
No files matched your search
@@ -69,10 +69,11 @@ public class NetNeutrality {
|
||||
private void startup() {
|
||||
// DatabaseMigration.migrate();
|
||||
SessionManager.getSessionFactory();
|
||||
initJDA();
|
||||
CommandManager.init(jda);
|
||||
MusicManager.initPlayerManager();
|
||||
TaskManager.getInstance().init();
|
||||
initJDA();
|
||||
CommandManager.registerSlashCommands(jda);
|
||||
jda.addEventListener(new ServerJoinHook());
|
||||
jda.addEventListener(new MessageReceivedHook(), new SlashCommandHook());
|
||||
jda.addEventListener(new ModalInteractionHook(), new ButtonInteractionHook(), new EmojiReactionHook());
|
||||
|
||||
@@ -6,9 +6,6 @@ package me.bobert.netneutrality.command;
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
@@ -34,11 +31,4 @@ public abstract class AbstractCommand implements Command {
|
||||
public boolean canBeExecutedFrom(MessageChannel channel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
// Prefer slash commands
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,12 @@ package me.bobert.netneutrality.command;
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public interface Command {
|
||||
|
||||
@@ -28,9 +26,9 @@ public interface Command {
|
||||
|
||||
String getDescription();
|
||||
|
||||
DefaultMemberPermissions getSlashCommandPermission();
|
||||
void registerCommandOptions(CommandOptionsBuilder builder);
|
||||
|
||||
void registerSlashCommandOptions(SlashCommandData data);
|
||||
DefaultMemberPermissions getSlashCommandPermission();
|
||||
|
||||
CommandType getType();
|
||||
|
||||
@@ -38,8 +36,5 @@ public interface Command {
|
||||
|
||||
boolean canBeExecutedFrom(MessageChannel channel);
|
||||
|
||||
@Deprecated
|
||||
CommandExecutionResult execute(MessageCommandContext context);
|
||||
|
||||
CommandExecutionResult execute(SlashCommandContext context);
|
||||
CommandExecutionResult execute(CommandContext context);
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package me.bobert.netneutrality.command;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
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.interactions.commands.build.SubcommandGroupData;
|
||||
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CommandOptions {
|
||||
private final Command command;
|
||||
private final SlashCommandData commandData;
|
||||
private final List<OptionData> options;
|
||||
private final List<SubcommandData> subcommands;
|
||||
private final List<SubcommandGroupData> subcommandGroups;
|
||||
|
||||
public CommandOptions(Command command, CommandDataImpl commandData) {
|
||||
this.command = command;
|
||||
this.commandData = commandData;
|
||||
this.options = commandData.getOptions();
|
||||
this.subcommands = commandData.getSubcommands();
|
||||
this.subcommandGroups = commandData.getSubcommandGroups();
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public SlashCommandData getSlashCommandData() {
|
||||
return commandData;
|
||||
}
|
||||
|
||||
public List<OptionData> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public List<SubcommandData> getSubcommands() {
|
||||
return subcommands;
|
||||
}
|
||||
|
||||
public List<SubcommandGroupData> getSubcommandGroups() {
|
||||
return subcommandGroups;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return options.isEmpty() && subcommands.isEmpty() && subcommandGroups.isEmpty();
|
||||
}
|
||||
|
||||
public String printUsage() {
|
||||
//TODO: show available choices if option has them
|
||||
StringBuilder usage = new StringBuilder();
|
||||
if (!options.isEmpty()) {
|
||||
usage.append("- Usage: /").append(command.getCommandName());
|
||||
for (OptionData option : options) {
|
||||
usage.append(" <").append(option.getName()).append(">");
|
||||
}
|
||||
|
||||
for (OptionData option : options) {
|
||||
usage.append("\n - ");
|
||||
if (option.isRequired()) {
|
||||
usage.append("*");
|
||||
}
|
||||
usage.append(option.getName()).append(": ").append(option.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
if (!subcommands.isEmpty()) {
|
||||
for (SubcommandData subcommand : subcommands) {
|
||||
usage.append("- Usage: /").append(command.getCommandName()).append(" ").append(subcommand.getName());
|
||||
for (OptionData option : subcommand.getOptions()) {
|
||||
usage.append(" <").append(option.getName()).append(">");
|
||||
}
|
||||
|
||||
for (OptionData option : subcommand.getOptions()) {
|
||||
usage.append("\n - ");
|
||||
if (option.isRequired()) {
|
||||
usage.append("*");
|
||||
}
|
||||
usage.append(option.getName()).append(": ").append(option.getDescription());
|
||||
}
|
||||
|
||||
usage.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!subcommandGroups.isEmpty()) {
|
||||
for (SubcommandGroupData subcommandGroup : subcommandGroups) {
|
||||
usage.append("- Subcommand: /").append(command.getCommandName())
|
||||
.append(" ").append(subcommandGroup.getName())
|
||||
.append(" (Description: ").append(subcommandGroup.getDescription()).append(")")
|
||||
.append("\n");
|
||||
|
||||
for (SubcommandData subcommand : subcommandGroup.getSubcommands()) {
|
||||
usage.append(" - Usage: /").append(command.getCommandName())
|
||||
.append(" ").append(subcommandGroup.getName())
|
||||
.append(" ").append(subcommand.getName());
|
||||
|
||||
for (OptionData option : subcommand.getOptions()) {
|
||||
usage.append(" <").append(option.getName()).append(">");
|
||||
}
|
||||
usage.append(" (Description: ").append(subcommand.getDescription()).append(")");
|
||||
|
||||
for (OptionData option : subcommand.getOptions()) {
|
||||
usage.append("\n - ");
|
||||
if (option.isRequired()) {
|
||||
usage.append("*");
|
||||
}
|
||||
usage.append(option.getName()).append(": ").append(option.getDescription());
|
||||
}
|
||||
|
||||
usage.append("\n");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEmpty()) {
|
||||
usage.append("\n\n-# *: required argument");
|
||||
}
|
||||
|
||||
return usage.toString();
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,13 @@ package me.bobert.netneutrality.command.admin;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractAdminCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.db.entities.OBlacklist;
|
||||
import me.bobert.netneutrality.db.repository.BlacklistRepository;
|
||||
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 java.util.List;
|
||||
@@ -41,25 +40,20 @@ public class BlacklistCommand extends AbstractAdminCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
data.addSubcommands(
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.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"),
|
||||
.addOption(OptionType.STRING, "word", "Word to add", true),
|
||||
new SubcommandData("remove", "Remove a word from the blacklist")
|
||||
.addOption(OptionType.STRING, "word", "Word to remove")
|
||||
.addOption(OptionType.STRING, "word", "Word to remove", true)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
String sub = context.getEvent().getFullCommandName().split(" ")[1];
|
||||
String word = context.getEvent().getOption("word", "", OptionMapping::getAsString);
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
String sub = context.getSubcommand();
|
||||
String word = context.getOption("word", "", CommandOption::getAsString);
|
||||
BlacklistRepository repository = new BlacklistRepository();
|
||||
|
||||
switch (sub) {
|
||||
|
||||
@@ -6,14 +6,14 @@ package me.bobert.netneutrality.command.admin;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractAdminCommand;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.core.tasks.TaskManager;
|
||||
import me.bobert.netneutrality.tasks.emoji.EmojiReactionRoleTask;
|
||||
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.interactions.commands.build.SubcommandGroupData;
|
||||
|
||||
@@ -40,8 +40,8 @@ public class ReactionCommand extends AbstractAdminCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
data.addSubcommandGroups(
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.addSubcommandGroups(
|
||||
new SubcommandGroupData("emoji", "Give roles to users using emojis").addSubcommands(
|
||||
new SubcommandData("setup", "Add a role to a message").addOptions(
|
||||
new OptionData(OptionType.STRING, "messageid", "The ID of the message", true),
|
||||
@@ -65,19 +65,19 @@ public class ReactionCommand extends AbstractAdminCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
context.ack();
|
||||
|
||||
String guildId = context.getGuild().getId();
|
||||
String messageId = context.getEvent().getOption("messageid", OptionMapping::getAsString);
|
||||
String sub = context.getSubCommand();
|
||||
String action = context.getEvent().getFullCommandName().split(" ")[2];
|
||||
String messageId = context.getOption("messageid", CommandOption::getAsString);
|
||||
String group = context.getSubcommandGroup();
|
||||
String sub = context.getSubcommand();
|
||||
|
||||
switch (sub) {
|
||||
switch (group) {
|
||||
case "emoji" -> {
|
||||
if ("setup".equals(action)) {
|
||||
String emoji = context.getEvent().getOption("emoji", OptionMapping::getAsString);
|
||||
String role = context.getEvent().getOption("role", OptionMapping::getAsString);
|
||||
if ("setup".equals(sub)) {
|
||||
String emoji = context.getOption("emoji", CommandOption::getAsString);
|
||||
String role = context.getOption("role", CommandOption::getAsString);
|
||||
|
||||
EmojiReactionRoleTask task = new EmojiReactionRoleTask(guildId, messageId);
|
||||
if (TaskManager.getInstance().exists(task.getId())) {
|
||||
@@ -89,9 +89,9 @@ public class ReactionCommand extends AbstractAdminCommand {
|
||||
return CommandExecutionResult.success("Added emoji to message successfully!");
|
||||
}
|
||||
|
||||
if ("add".equals(action)) {
|
||||
String emoji = context.getEvent().getOption("emoji", OptionMapping::getAsString);
|
||||
String role = context.getEvent().getOption("role", OptionMapping::getAsString);
|
||||
if ("add".equals(sub)) {
|
||||
String emoji = context.getOption("emoji", CommandOption::getAsString);
|
||||
String role = context.getOption("role", CommandOption::getAsString);
|
||||
|
||||
String id = String.format("%s:%s", guildId, messageId);
|
||||
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
||||
@@ -104,8 +104,8 @@ public class ReactionCommand extends AbstractAdminCommand {
|
||||
return CommandExecutionResult.success("Added emoji to message successfully!");
|
||||
}
|
||||
|
||||
if ("remove".equals(action)) {
|
||||
String emoji = context.getEvent().getOption("emoji", OptionMapping::getAsString);
|
||||
if ("remove".equals(sub)) {
|
||||
String emoji = context.getOption("emoji", CommandOption::getAsString);
|
||||
|
||||
String id = String.format("%s:%s", guildId, messageId);
|
||||
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
||||
@@ -118,7 +118,7 @@ public class ReactionCommand extends AbstractAdminCommand {
|
||||
return CommandExecutionResult.success("Removed emoji from message successfully!");
|
||||
}
|
||||
|
||||
if ("delete".equals(action)) {
|
||||
if ("delete".equals(sub)) {
|
||||
String id = String.format("%s:%s", guildId, messageId);
|
||||
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
||||
if (task == null) {
|
||||
|
||||
@@ -6,24 +6,21 @@ package me.bobert.netneutrality.command.basic;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractCommand;
|
||||
import me.bobert.netneutrality.command.Command;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.command.CommandType;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandContainer;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.CommandManager;
|
||||
import me.bobert.netneutrality.core.context.Context;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.core.tasks.BuiltInTask;
|
||||
import me.bobert.netneutrality.tasks.help.BotInfo;
|
||||
import me.bobert.netneutrality.tasks.help.CommandHelp;
|
||||
import me.bobert.netneutrality.tasks.help.ReportBug;
|
||||
import me.bobert.netneutrality.utils.MessageFunction;
|
||||
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.components.ActionRow;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -55,9 +52,8 @@ public class HelpCommand extends AbstractCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
|
||||
data.addOption(OptionType.STRING, "command", "The name of the command you want help with", false);
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.addOption(OptionType.STRING, "command", "The name of the command you want help with", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,37 +62,25 @@ public class HelpCommand extends AbstractCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
context.reply(new MessageCreateBuilder().addContent(context.getDiscordUser().getAsMention()).addContent(" help has been sent your way!").build());
|
||||
sendHelp(context, context.getArgument(0));
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
sendHelp(context, context.getEvent().getOption("command", null, OptionMapping::getAsString));
|
||||
|
||||
return CommandExecutionResult.success("Help has been sent in DM!");
|
||||
}
|
||||
|
||||
public void sendHelp(Context context, String commandStr) {
|
||||
if (commandStr == null) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
String command = context.getOption("command", null, CommandOption::getAsString);
|
||||
if (command == null) {
|
||||
Button commands = BuiltInTask.createButton(CommandHelp.class).primary("Commands");
|
||||
Button info = BuiltInTask.createButton(BotInfo.class).primary("Info");
|
||||
Button reportbug = BuiltInTask.createButton(ReportBug.class).danger("Report bug");
|
||||
ActionRow row = ActionRow.of(commands, info, reportbug);
|
||||
context.replyEphemeral("Help has been sent in DM!");
|
||||
context.sendMessageInPrivate("Thanks for using the Net Neutrality Bot! What do you need help with?", List.of(row));
|
||||
return;
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
Command command = CommandManager.getCommand(commandStr);
|
||||
if (command == null) {
|
||||
context.reply("Command does not exist");
|
||||
return;
|
||||
CommandContainer container = CommandManager.getCommandContainer(command);
|
||||
if (container.getCommand() == null) {
|
||||
return CommandExecutionResult.warn("Command does not exist");
|
||||
}
|
||||
|
||||
context.reply(MessageFunction.buildCommandHelpMessage(command));
|
||||
context.replyEphemeral("Help has been sent in DM!");
|
||||
context.sendMessageInPrivate(MessageFunction.buildCommandHelpMessage(container));
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,10 +7,9 @@ package me.bobert.netneutrality.command.basic;
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractCommand;
|
||||
import me.bobert.netneutrality.command.CommandType;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
|
||||
public class PingCommand extends AbstractCommand {
|
||||
|
||||
@@ -40,7 +39,7 @@ public class PingCommand extends AbstractCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@@ -50,15 +49,7 @@ public class PingCommand extends AbstractCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
if (context.getArgs().isEmpty())
|
||||
context.reply(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing()));
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
return CommandExecutionResult.success(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing()));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,23 +6,21 @@ package me.bobert.netneutrality.command.bot;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractAdminCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.GuildManager;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.db.GSettings;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
|
||||
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 java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfigureCommand extends AbstractAdminCommand {
|
||||
@@ -48,8 +46,8 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
data.addSubcommands(
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.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)),
|
||||
@@ -63,143 +61,13 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
Map<Integer, String> args = context.getArgs();
|
||||
GuildManager guildManager = GuildManager.getManager(context.getGuild());
|
||||
|
||||
if (!args.isEmpty()) {
|
||||
|
||||
// Role for music commands
|
||||
if (context.getArgument(0).equals("music-role")) {
|
||||
if (args.size() == 1) {
|
||||
String roleDb = guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_ROLE);
|
||||
Role role = null;
|
||||
if (!roleDb.isEmpty()) {
|
||||
role = context.getGuild().getRoleById(roleDb);
|
||||
}
|
||||
|
||||
context.reply("Current role needed to use music commands (default is everyone): %s", (role == null ? "Everyone" : role.getAsMention()));
|
||||
context.reply("Reset role using 'conf music-role reset' or set it using 'conf musicrole @'");
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
if (context.getArgument(1).equals("reset")) {
|
||||
if (!guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_ROLE).isEmpty()) {
|
||||
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_ROLE, null);
|
||||
}
|
||||
|
||||
context.reply("Successful reset of the role");
|
||||
}
|
||||
|
||||
List<Role> roles = context.getMessage().getMentions().getRoles();
|
||||
if (roles.size() == 1) {
|
||||
Role role = roles.get(0);
|
||||
if (role.getGuild().getId().equals(context.getGuild().getId())) {
|
||||
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_ROLE, role.getId());
|
||||
context.reply("Successfully set %s as the role needed for music command", role.getAsMention());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Role for music commands
|
||||
if (context.getArgument(0).equals("music-channel")) {
|
||||
if (args.size() == 1) {
|
||||
String channelDb = guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_CHANNEL);
|
||||
TextChannel channel = null;
|
||||
if (!channelDb.isEmpty()) {
|
||||
channel = context.getGuild().getTextChannelById(channelDb);
|
||||
}
|
||||
|
||||
context.reply("Current channel where music commands can be executed (default is everywhere): %s", (channel == null ? "Everywhere" : channel.getAsMention()));
|
||||
context.reply("Reset channel using 'conf music-channel reset' or set it using 'conf music-channel #'");
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
if (context.getArgument(1).equals("reset")) {
|
||||
if (!guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_CHANNEL).isEmpty()) {
|
||||
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_CHANNEL, null);
|
||||
}
|
||||
|
||||
context.reply("Successful reset of the channel");
|
||||
}
|
||||
|
||||
List<TextChannel> channels = context.getMessage().getMentions().getChannels(TextChannel.class);
|
||||
if (channels.size() == 1) {
|
||||
TextChannel channel = channels.get(0);
|
||||
if (channel.getGuild().getId().equals(context.getGuild().getId())) {
|
||||
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_CHANNEL, channel.getId());
|
||||
context.reply("Successfully set %s as the channel required to execute music command", channel.getAsMention());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default volume for music player
|
||||
if (context.getArgument(0).equals("music-volume")) {
|
||||
if (args.size() == 1) {
|
||||
int volume = Integer.parseInt(guildManager.getGuildConfigManager().getSetting(GSettings.MUSIC_VOLUME));
|
||||
|
||||
context.reply("Default volume for music player: %d", volume);
|
||||
context.reply("Set using 'conf music-volume <value between 0 and 100>'");
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
try {
|
||||
int volume = Integer.parseInt(args.get(1));
|
||||
|
||||
if (volume > 0 && volume <= 100) {
|
||||
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_VOLUME, String.valueOf(volume));
|
||||
MusicManager.get(context.getGuild()).setVolume(volume);
|
||||
|
||||
context.reply("Default volume for music player is now %d", volume);
|
||||
} else
|
||||
throw new NumberFormatException();
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
context.reply("Not a value between 0 and 100");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug
|
||||
if (context.getArgument(0).equals("debug")) {
|
||||
if (args.size() == 1) {
|
||||
boolean debug = guildManager.isDebugEnabled();
|
||||
|
||||
context.reply("Error logging is currently %s for this guild.", (debug ? "enabled" : "disabled"));
|
||||
context.reply("Use 'conf debug 0/1' to toggle between states (0 = disabled, 1 = enabled).");
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
String str = args.get(1);
|
||||
boolean debug = guildManager.isDebugEnabled();
|
||||
if (str.equals("0") || str.equalsIgnoreCase("disable")) {
|
||||
debug = false;
|
||||
}
|
||||
|
||||
if (str.equals("1") || str.equalsIgnoreCase("enable")) {
|
||||
debug = true;
|
||||
}
|
||||
|
||||
guildManager.setDebug(debug);
|
||||
context.reply("Error logging is now %s for this guild", (debug ? "enabled" : "disabled"));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
String sub = context.getEvent().getFullCommandName().split(" ")[1];
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
String sub = context.getSubcommand();
|
||||
GuildManager guildManager = GuildManager.getManager(context.getGuild());
|
||||
context.ephemeral();
|
||||
|
||||
if ("music-role".equals(sub)) {
|
||||
Role role = context.getEvent().getOption("role", OptionMapping::getAsRole);
|
||||
Role role = context.getOption("role", CommandOption::getAsRole);
|
||||
assert role != null;
|
||||
|
||||
if (role.getPosition() == -1) {
|
||||
@@ -216,7 +84,7 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
||||
}
|
||||
|
||||
if ("music-channel".equals(sub)) {
|
||||
GuildChannelUnion channel = context.getEvent().getOption("channel", OptionMapping::getAsChannel);
|
||||
GuildChannelUnion channel = context.getOption("channel", CommandOption::getAsChannel);
|
||||
|
||||
if (channel == null) {
|
||||
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_CHANNEL, null);
|
||||
@@ -235,7 +103,7 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
||||
}
|
||||
|
||||
if ("music-volume".equals(sub)) {
|
||||
int volume = context.getEvent().getOption("volume", 30, OptionMapping::getAsInt);
|
||||
int volume = context.getOption("volume", 30, CommandOption::getAsInt);
|
||||
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_VOLUME, String.valueOf(volume));
|
||||
MusicManager.get(context.getGuild()).setVolume(volume);
|
||||
|
||||
@@ -243,7 +111,7 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
||||
}
|
||||
|
||||
if ("error-logging".equals(sub)) {
|
||||
boolean debug = context.getEvent().getOption("debug", true, OptionMapping::getAsBoolean);
|
||||
boolean debug = context.getOption("debug", true, CommandOption::getAsBoolean);
|
||||
guildManager.setDebug(debug);
|
||||
|
||||
return CommandExecutionResult.success("Error logging is now %s for this guild", (debug ? "enabled" : "disabled"));
|
||||
|
||||
@@ -6,22 +6,20 @@ package me.bobert.netneutrality.command.crypto;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractCommand;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.command.CommandType;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.LogHandler;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.http.WebModule;
|
||||
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 org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Currency;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class CryptoPriceCommand extends AbstractCommand {
|
||||
|
||||
@@ -53,9 +51,9 @@ public class CryptoPriceCommand extends AbstractCommand {
|
||||
}
|
||||
|
||||
@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");
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.addOption(OptionType.STRING, "symbol", "The crypto symbol to fetch price for", true);
|
||||
builder.addOption(OptionType.STRING, "currency", "In which currency should the price be displayed");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,59 +62,13 @@ public class CryptoPriceCommand extends AbstractCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
Map<Integer, String> args = context.getArgs();
|
||||
String currency = "USD";
|
||||
|
||||
if (args.isEmpty()) {
|
||||
return CommandExecutionResult.warn("Usage: crypto <symbol> <currency>");
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
try {
|
||||
currency = Currency.getInstance(args.get(1).toUpperCase()).getCurrencyCode();
|
||||
} catch (IllegalArgumentException exception) {
|
||||
return CommandExecutionResult.warn("Please enter a valid currency");
|
||||
}
|
||||
}
|
||||
|
||||
String crypto = args.get(0).toUpperCase();
|
||||
String finalCurrency = currency;
|
||||
|
||||
context.async("Retreiving price, please wait...", asyncMessage -> {
|
||||
String price;
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
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"))) {
|
||||
asyncMessage.edit("Crypto doesn't exist.. yet");
|
||||
return;
|
||||
}
|
||||
|
||||
price = dollarFormat.format(json.getDouble(finalCurrency));
|
||||
asyncMessage.edit("The current price of %s in %s is %s", crypto, finalCurrency, price);
|
||||
|
||||
} catch (JSONException | IllegalArgumentException | ArithmeticException e) {
|
||||
asyncMessage.edit("Error getting price of %s", crypto);
|
||||
LogHandler.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult 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);
|
||||
String symbol = context.getOption("symbol", CommandOption::getAsString);
|
||||
String currency = context.getOption("currency", "USD", CommandOption::getAsString).toUpperCase();
|
||||
|
||||
try {
|
||||
currency = Currency.getInstance(currency).getCurrencyCode();
|
||||
|
||||
@@ -7,12 +7,12 @@ package me.bobert.netneutrality.command.git;
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractCommand;
|
||||
import me.bobert.netneutrality.command.CommandType;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.core.tasks.TaskManager;
|
||||
import me.bobert.netneutrality.tasks.git.ReportIssueTask;
|
||||
import me.bobert.netneutrality.utils.Settings;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class ReportIssueCommand extends AbstractCommand {
|
||||
@Override
|
||||
@@ -41,7 +41,7 @@ public class ReportIssueCommand extends AbstractCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class ReportIssueCommand extends AbstractCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
String gitlabHost = Settings.getInstance().get("GITLAB_HOST");
|
||||
String gitlabToken = Settings.getInstance().get("GITLAB_TOKEN");
|
||||
String projectId = Settings.getInstance().get("GITLAB_PROJECT_ID");
|
||||
|
||||
@@ -8,11 +8,10 @@ package me.bobert.netneutrality.command.music;
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.command.CommandType;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class BitconnectCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -32,7 +31,7 @@ public class BitconnectCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@@ -42,18 +41,10 @@ public class BitconnectCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
MusicManager player = MusicManager.get(context.getGuild());
|
||||
player.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, true);
|
||||
|
||||
context.deleteMessage();
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
context.ephemeral();
|
||||
context.deleteMessage();
|
||||
|
||||
manager.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, true);
|
||||
return CommandExecutionResult.success("Ready to invest?");
|
||||
|
||||
@@ -7,11 +7,11 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class ClearQueueCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -36,12 +36,12 @@ public class ClearQueueCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
context.ack();
|
||||
|
||||
|
||||
@@ -7,13 +7,12 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MessageFunction;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class CurrentlyPlayingCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -33,27 +32,12 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
// no arguments
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
if (!manager.isCurrentlyPlaying()) {
|
||||
return CommandExecutionResult.info("Bot isn't playing any tracks right now");
|
||||
}
|
||||
|
||||
context.reply(MessageFunction.buildCurrentlyPlayingMessage(manager));
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
context.ack();
|
||||
|
||||
|
||||
@@ -7,11 +7,10 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class JoinCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -31,21 +30,12 @@ public class JoinCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
if (MusicUtils.connect(context)) {
|
||||
context.reply("Joining current voice channel");
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
if (MusicUtils.connect(context)) {
|
||||
context.reply("Joining current voice channel");
|
||||
}
|
||||
|
||||
@@ -7,12 +7,11 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class LeaveCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -32,24 +31,12 @@ public class LeaveCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
context.reply("Leaving voice channel and clearing queue");
|
||||
manager.disconnect();
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
|
||||
@@ -7,13 +7,12 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
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;
|
||||
|
||||
public class PlayCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -33,26 +32,14 @@ public class PlayCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
data.addOption(OptionType.STRING, "query", "URL or search query", true);
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.addOption(OptionType.STRING, "query", "URL or search query", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (context.getArgs().isEmpty()) {
|
||||
return CommandExecutionResult.warn("Please specify a query");
|
||||
}
|
||||
|
||||
manager.play(context.getMessageText(), context);
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
String query = context.getEvent().getOption("query", OptionMapping::getAsString);
|
||||
String query = context.getOption("query", CommandOption::getAsString);
|
||||
context.ack();
|
||||
|
||||
manager.play(query, context);
|
||||
|
||||
@@ -6,17 +6,17 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MessageFunction;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
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;
|
||||
|
||||
public class QueueCommand extends AbstractMusicCommand {
|
||||
@@ -37,14 +37,8 @@ public class QueueCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultMemberPermissions getSlashCommandPermission() {
|
||||
return DefaultMemberPermissions.DISABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
|
||||
data.addSubcommands(
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.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)
|
||||
@@ -59,9 +53,14 @@ public class QueueCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public DefaultMemberPermissions getSlashCommandPermission() {
|
||||
return DefaultMemberPermissions.DISABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
String sub = context.getSubCommand();
|
||||
String sub = context.getSubcommand();
|
||||
context.ack();
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
@@ -72,7 +71,7 @@ public class QueueCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
case "delete-track" -> {
|
||||
int position = context.getEvent().getOption("position", 0, OptionMapping::getAsInt);
|
||||
int position = context.getOption("position", 0, CommandOption::getAsInt);
|
||||
return manager.getQueueManager().removeFromQueue(position);
|
||||
}
|
||||
|
||||
@@ -83,7 +82,7 @@ public class QueueCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
case "from-user" -> {
|
||||
Member user = context.getEvent().getOption("user", OptionMapping::getAsMember);
|
||||
Member user = context.getOption("user", CommandOption::getAsMember);
|
||||
if (user == null) {
|
||||
return CommandExecutionResult.warn("The user isn't from this guild");
|
||||
}
|
||||
@@ -92,7 +91,7 @@ public class QueueCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
case "remove-from-user" -> {
|
||||
Member member = context.getEvent().getOption("user", OptionMapping::getAsMember);
|
||||
Member member = context.getOption("user", CommandOption::getAsMember);
|
||||
if (member == null) {
|
||||
return CommandExecutionResult.warn("The user isn't from this guild");
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ package me.bobert.netneutrality.command.music;/*
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class ResumeCommand extends AbstractMusicCommand {
|
||||
@Override
|
||||
@@ -28,12 +28,12 @@ public class ResumeCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
|
||||
@@ -7,11 +7,11 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class ShuffleCommand extends AbstractMusicCommand {
|
||||
@Override
|
||||
@@ -30,12 +30,12 @@ public class ShuffleCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
context.ack();
|
||||
|
||||
|
||||
@@ -7,16 +7,15 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import me.bobert.netneutrality.utils.UserFunction;
|
||||
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;
|
||||
|
||||
public class SkipCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -36,45 +35,23 @@ public class SkipCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
data.addOptions(new OptionData(OptionType.INTEGER, "skip", "Number of tracks to skip")
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.addOptions(new OptionData(OptionType.INTEGER, "skip", "Number of tracks to skip")
|
||||
.setMinValue(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (!MusicUtils.checkIfConnected(context)) {
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
if (UserFunction.isAdmin(context.getGuildUser()) || MusicUtils.isUserDj(context.getGuildUser())) {
|
||||
if (UserFunction.isAdmin(context.getGuildUser()) && !context.getArgs().isEmpty()) {
|
||||
try {
|
||||
int skips = Integer.parseInt(context.getArgument(0));
|
||||
return manager.getQueueManager().skip(skips);
|
||||
} catch (NumberFormatException e) {
|
||||
context.reply("Please enter how many track(s) to skip");
|
||||
}
|
||||
} else {
|
||||
return manager.getQueueManager().skip(1);
|
||||
}
|
||||
} else {
|
||||
return manager.voteSkip(context);
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
context.ack();
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
int skips = context.getEvent().getOption("skip", 1, OptionMapping::getAsInt);
|
||||
int skips = context.getOption("skip", 1, CommandOption::getAsInt);
|
||||
if (UserFunction.isAdmin(context) || MusicUtils.isUserDj(context)) {
|
||||
return manager.getQueueManager().skip(skips);
|
||||
} else {
|
||||
return manager.voteSkip(context);
|
||||
}
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
|
||||
@@ -7,13 +7,12 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import me.bobert.netneutrality.utils.UserFunction;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class StopCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -33,17 +32,17 @@ public class StopCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
context.ack();
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
// Need a resume command before
|
||||
if (UserFunction.isAdmin(context.getGuildUser())) {
|
||||
if (UserFunction.isAdmin(context)) {
|
||||
manager.stopTrack();
|
||||
context.reply("Stopping current track");
|
||||
}
|
||||
@@ -51,17 +50,4 @@ public class StopCommand extends AbstractMusicCommand {
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
context.ack();
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
manager.stopTrack();
|
||||
return CommandExecutionResult.success("Stopping music playback");
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,12 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MessageFunction;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class ViewQueueCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -32,28 +31,12 @@ public class ViewQueueCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
int queueSize = manager.getQueueSize();
|
||||
if (queueSize > 0) {
|
||||
context.reply(MessageFunction.buildViewQueueMessage(manager));
|
||||
} else {
|
||||
context.reply("Queue is empty!");
|
||||
}
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
context.ack();
|
||||
|
||||
|
||||
@@ -7,16 +7,15 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import me.bobert.netneutrality.utils.UserFunction;
|
||||
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;
|
||||
|
||||
public class VolumeCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -36,45 +35,22 @@ public class VolumeCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
data.addOptions(new OptionData(OptionType.INTEGER, "volume", "Playback volume for this session", true)
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
builder.addOptions(new OptionData(OptionType.INTEGER, "volume", "Playback volume for this session", true)
|
||||
.setRequiredRange(0, 100));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (!MusicUtils.checkIfConnected(context))
|
||||
return CommandExecutionResult.none();
|
||||
|
||||
if (UserFunction.isAdmin(context.getGuildUser()) || MusicUtils.isUserDj(context.getGuildUser())) {
|
||||
try {
|
||||
int volume = Integer.parseInt(context.getArgument(0));
|
||||
|
||||
if (volume > 0 && volume <= 100) {
|
||||
manager.setVolume(volume);
|
||||
context.reply("Volume set to %s", volume);
|
||||
} else
|
||||
throw new NumberFormatException();
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
context.reply("Please enter a value from 0 to 100");
|
||||
}
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
int volume = context.getEvent().getOption("volume", 30, OptionMapping::getAsInt);
|
||||
int volume = context.getOption("volume", 30, CommandOption::getAsInt);
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
if (UserFunction.isAdmin(context) || MusicUtils.isUserDj(context)) {
|
||||
manager.setVolume(volume);
|
||||
return CommandExecutionResult.success(String.format("Volume set to %s", volume));
|
||||
}
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@@ -6,12 +6,11 @@ package me.bobert.netneutrality.command.music;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
import me.bobert.netneutrality.utils.MusicUtils;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
|
||||
public class VoteSkipCommand extends AbstractMusicCommand {
|
||||
|
||||
@@ -31,23 +30,12 @@ public class VoteSkipCommand extends AbstractMusicCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
||||
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
return manager.voteSkip(context);
|
||||
}
|
||||
|
||||
return CommandExecutionResult.none();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
||||
public CommandExecutionResult execute(CommandContext context) {
|
||||
MusicManager manager = MusicManager.get(context.getGuild());
|
||||
|
||||
if (MusicUtils.checkIfConnected(context)) {
|
||||
|
||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.context;
|
||||
|
||||
import me.bobert.netneutrality.core.context.AbstractContext;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.events.Event;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
|
||||
@@ -38,6 +39,11 @@ public class AsyncContext extends AbstractContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelType getType() {
|
||||
return ChannelType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionHook getInteractionHook() {
|
||||
return hook;
|
||||
@@ -59,7 +65,7 @@ public class AsyncContext extends AbstractContext {
|
||||
hook.deleteOriginal().queue();
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
if (message != null && getType() != ChannelType.PRIVATE) {
|
||||
message.delete().queue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,18 +5,26 @@ package me.bobert.netneutrality.context;
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.command.options.MessageCommandOption;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.utils.Settings;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import net.dv8tion.jda.api.interactions.commands.Command;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
|
||||
import net.dv8tion.jda.api.interactions.modals.Modal;
|
||||
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -35,35 +43,9 @@ public class MessageCommandContext extends CommandContext {
|
||||
return event;
|
||||
}
|
||||
|
||||
public String getArgument(int index) {
|
||||
return getArgs().get(index);
|
||||
}
|
||||
|
||||
public Map<Integer, String> getArgs() {
|
||||
Map<Integer, String> args = new HashMap<>();
|
||||
|
||||
String msg = message.getContentDisplay().trim();
|
||||
msg = msg.substring(Settings.getInstance().getPrefix().length()).trim();
|
||||
String cmd = msg.split(" ", 2)[0];
|
||||
|
||||
String[] array = msg.replaceFirst("(" + cmd + ")(\\s+)?", "").split(" ");
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
args.put(i, array[i]);
|
||||
}
|
||||
|
||||
if (args.size() == 1 && args.get(0).isEmpty()) {
|
||||
args.remove(0);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
public String getMessageText() {
|
||||
String msg = message.getContentDisplay().trim();
|
||||
msg = msg.substring(Settings.getInstance().getPrefix().length()).trim();
|
||||
String cmd = msg.split(" ", 2)[0];
|
||||
|
||||
return msg.replaceFirst("(" + cmd + ")( )?", "");
|
||||
@Override
|
||||
public ChannelType getType() {
|
||||
return event.getChannelType();
|
||||
}
|
||||
|
||||
public Message getMessage() {
|
||||
@@ -102,11 +84,6 @@ public class MessageCommandContext extends CommandContext {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replyEphemeral(MessageCreateData messageCreateData) {
|
||||
sendMessageInPrivate(messageCreateData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ack(boolean ephemeral) {
|
||||
|
||||
@@ -114,19 +91,206 @@ public class MessageCommandContext extends CommandContext {
|
||||
|
||||
@Override
|
||||
public void deleteMessage() {
|
||||
if (message != null) {
|
||||
if (message != null && getType() != ChannelType.PRIVATE) {
|
||||
message.delete().queueAfter(1, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMessageFromOwner() {
|
||||
return getGuildUser().isOwner();
|
||||
@Override
|
||||
public List<CommandOption> parseOptions(String[] args, List<OptionData> commandOptions) {
|
||||
List<CommandOption> options = new ArrayList<>();
|
||||
Mentions mentions = message.getMentions();
|
||||
int roleMentionIndex = 0;
|
||||
int userMentionIndex = 0;
|
||||
int memberMentionIndex = 0;
|
||||
int channelMentionIndex = 0;
|
||||
int index = 0;
|
||||
|
||||
for (OptionData data : commandOptions) {
|
||||
OptionType type = data.getType();
|
||||
Set<ChannelType> requiredChannelTypes = data.getChannelTypes();
|
||||
List<Command.Choice> choices = data.getChoices();
|
||||
Object value = null;
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case STRING -> {
|
||||
//TODO: check length
|
||||
String str = args[index];
|
||||
|
||||
if (str.contains("<@") && str.contains(">")) {
|
||||
invalidateContext(data, "expected a string at index " + index + " but a role/user/channel was provided");
|
||||
break;
|
||||
}
|
||||
|
||||
public boolean isMessageFromCreator() {
|
||||
String creatorId = Settings.getInstance().get("NETNEUTRALITY_BOT_OWNER");
|
||||
if (!choices.isEmpty()) {
|
||||
List<Command.Choice> matched = choices.stream().filter(choice -> choice.getAsString().equalsIgnoreCase(str)).toList();
|
||||
if (matched.isEmpty()) {
|
||||
invalidateContext(data, "not a valid choice, valid choices are: " + validChoices(choices));
|
||||
}
|
||||
}
|
||||
|
||||
return creatorId.equals(getDiscordUser().getId());
|
||||
Integer min = data.getMinLength();
|
||||
Integer max = data.getMaxLength();
|
||||
|
||||
if (min != null && str.length() < min) {
|
||||
invalidateContext(data, "minimum length for argument is " + min);
|
||||
}
|
||||
|
||||
if (max != null && str.length() > max) {
|
||||
invalidateContext(data, "maximum length for argument is " + max);
|
||||
}
|
||||
|
||||
value = str;
|
||||
}
|
||||
case INTEGER -> {
|
||||
long num = Long.parseLong(args[index]);
|
||||
if (!choices.isEmpty()) {
|
||||
List<Command.Choice> matched = choices.stream().filter(choice -> choice.getAsLong() == num).toList();
|
||||
if (matched.isEmpty()) {
|
||||
invalidateContext(data, "not a valid choice, valid choices are: " + validChoices(choices));
|
||||
}
|
||||
}
|
||||
value = num;
|
||||
|
||||
Number max = data.getMaxValue();
|
||||
Number min = data.getMinValue();
|
||||
|
||||
if (min != null && num < min.longValue()) {
|
||||
value = min.longValue();
|
||||
} else if (max != null && num > max.longValue()) {
|
||||
value = max.longValue();
|
||||
}
|
||||
|
||||
value = num;
|
||||
}
|
||||
case BOOLEAN -> value = Boolean.parseBoolean(args[index]);
|
||||
case NUMBER -> {
|
||||
double num = Long.parseLong(args[index]);
|
||||
if (!choices.isEmpty()) {
|
||||
List<Command.Choice> matched = choices.stream().filter(choice -> choice.getAsDouble() == num).toList();
|
||||
if (matched.isEmpty()) {
|
||||
invalidateContext(data, "not a valid choice, valid choices are: " + validChoices(choices));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Number max = data.getMaxValue();
|
||||
Number min = data.getMinValue();
|
||||
value = num;
|
||||
|
||||
if (min != null && num < min.doubleValue()) {
|
||||
value = min.doubleValue();
|
||||
} else if (max != null && num > max.doubleValue()) {
|
||||
value = max.doubleValue();
|
||||
}
|
||||
}
|
||||
case ROLE -> {
|
||||
if (mentions.getRoles().size() > roleMentionIndex) {
|
||||
Role role = mentions.getRoles().get(roleMentionIndex++);
|
||||
if (role.getGuild().getId().equals(getGuild().getId())) {
|
||||
value = role;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
invalidateContext(data, "provided argument at index " + roleMentionIndex + " is not a valid role.");
|
||||
}
|
||||
case USER -> {
|
||||
if (mentions.getMembers().size() > memberMentionIndex) {
|
||||
Member member = mentions.getMembers().get(memberMentionIndex++);
|
||||
if (member.getGuild().getId().equals(getGuild().getId())) {
|
||||
value = member;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mentions.getUsers().size() > userMentionIndex) {
|
||||
value = mentions.getUsers().get(userMentionIndex++);
|
||||
break;
|
||||
}
|
||||
|
||||
invalidateContext(data, "provided argument is not a valid user.");
|
||||
}
|
||||
case MENTIONABLE -> {
|
||||
if (mentions.getRoles().size() > roleMentionIndex) {
|
||||
Role role = mentions.getRoles().get(roleMentionIndex++);
|
||||
if (role.getGuild().getId().equals(getGuild().getId())) {
|
||||
value = role;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (mentions.getMembers().size() > memberMentionIndex) {
|
||||
Member member = mentions.getMembers().get(memberMentionIndex++);
|
||||
if (member.getGuild().getId().equals(getGuild().getId())) {
|
||||
value = member;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (mentions.getUsers().size() > userMentionIndex) {
|
||||
value = mentions.getUsers().get(userMentionIndex++);
|
||||
break;
|
||||
}
|
||||
|
||||
invalidateContext(data, "provided argument is not a valid user or role.");
|
||||
}
|
||||
case CHANNEL -> {
|
||||
//TODO: check types
|
||||
if (mentions.getChannels().size() > channelMentionIndex) {
|
||||
GuildChannel channel = mentions.getChannels().get(channelMentionIndex++);
|
||||
|
||||
if (!requiredChannelTypes.contains(channel.getType())) {
|
||||
invalidateContext(data, "not a valid channel type at index " + channelMentionIndex +
|
||||
" , valid types are: " + validTypes(requiredChannelTypes));
|
||||
break;
|
||||
}
|
||||
|
||||
if (channel.getGuild().getId().equals(getGuild().getId())) {
|
||||
value = channel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
invalidateContext(data, "provided argument is not a valid channel.");
|
||||
}
|
||||
}
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
if (data.isRequired()) {
|
||||
// This should never happen because required options are validated before calling parseOptions()
|
||||
throw new IllegalArgumentException("Required option " + data.getName() + " was not found at index " + index);
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
invalidateContext(data, "the argument provided was not a number.");
|
||||
}
|
||||
|
||||
options.add(new MessageCommandOption(data, value));
|
||||
index++;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private String validChoices(List<Command.Choice> choices) {
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
for (Command.Choice choice : choices) {
|
||||
joiner.add(choice.getAsString());
|
||||
}
|
||||
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
private String validTypes(Set<ChannelType> types) {
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
for (ChannelType type : types) {
|
||||
joiner.add(type.name());
|
||||
}
|
||||
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,11 +309,10 @@ public class MessageCommandContext extends CommandContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubCommand() {
|
||||
if (!getArgs().isEmpty()) {
|
||||
return getArgument(0);
|
||||
}
|
||||
public String getFullCommand() {
|
||||
String rawMessage = message.getContentRaw().trim();
|
||||
String prefix = Settings.getInstance().getPrefix();
|
||||
|
||||
return "";
|
||||
return rawMessage.replaceFirst(String.format("^[%s\\s]{1,}", prefix), "").trim();
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.context;
|
||||
|
||||
import me.bobert.netneutrality.core.context.AbstractContext;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.events.Event;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
@@ -28,6 +29,11 @@ public class MusicChannelContext extends AbstractContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelType getType() {
|
||||
return getChannel().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionHook getInteractionHook() {
|
||||
return null;
|
||||
|
||||
@@ -5,11 +5,18 @@ package me.bobert.netneutrality.context;
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.core.command.options.SlashCommandOption;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.core.context.InteractionContext;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
import net.dv8tion.jda.api.interactions.modals.Modal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SlashCommandContext extends CommandContext implements InteractionContext {
|
||||
private final SlashCommandInteractionEvent event;
|
||||
|
||||
@@ -23,6 +30,11 @@ public class SlashCommandContext extends CommandContext implements InteractionCo
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelType getType() {
|
||||
return event.getChannelType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMessage() {
|
||||
// not implemented
|
||||
@@ -33,13 +45,28 @@ public class SlashCommandContext extends CommandContext implements InteractionCo
|
||||
event.replyModal(modal).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommandOption> parseOptions(String[] args, List<OptionData> commandOptions) {
|
||||
return event.getOptions().stream().map(SlashCommandOption::new).collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseCommandName() {
|
||||
return event.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubCommand() {
|
||||
return event.getFullCommandName().split(" ")[1];
|
||||
public String getFullCommand() {
|
||||
return event.getFullCommandName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubcommandGroup() {
|
||||
return getFullCommand().split(" ")[2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubcommand() {
|
||||
return getFullCommand().split(" ")[1];
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.context.tasks;
|
||||
|
||||
import me.bobert.netneutrality.core.context.InteractionContext;
|
||||
import me.bobert.netneutrality.core.context.TaskContext;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
|
||||
public class ButtonTaskContext extends TaskContext implements InteractionContext {
|
||||
@@ -22,6 +23,11 @@ public class ButtonTaskContext extends TaskContext implements InteractionContext
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelType getType() {
|
||||
return event.getChannelType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return event.getComponentId();
|
||||
|
||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.context.tasks;
|
||||
|
||||
import me.bobert.netneutrality.context.AsyncContext;
|
||||
import me.bobert.netneutrality.core.context.TaskContext;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
|
||||
@@ -30,6 +31,11 @@ public class EmojiTaskContext extends TaskContext {
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelType getType() {
|
||||
return event.getChannelType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return String.format("%s:%s", getGuild().getId(), event.getMessageId());
|
||||
@@ -64,6 +70,10 @@ public class EmojiTaskContext extends TaskContext {
|
||||
|
||||
@Override
|
||||
public void replyEphemeral(MessageCreateData messageCreateData) {
|
||||
if (getType() == ChannelType.PRIVATE) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendMessageInPrivate(messageCreateData);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.context.tasks;
|
||||
|
||||
import me.bobert.netneutrality.core.context.InteractionContext;
|
||||
import me.bobert.netneutrality.core.context.TaskContext;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
||||
|
||||
public class ModalTaskContext extends TaskContext implements InteractionContext {
|
||||
@@ -23,6 +24,11 @@ public class ModalTaskContext extends TaskContext implements InteractionContext
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelType getType() {
|
||||
return event.getChannelType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return event.getModalId();
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package me.bobert.netneutrality.core.command;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.Command;
|
||||
import me.bobert.netneutrality.command.CommandOptions;
|
||||
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||
|
||||
public class CommandContainer {
|
||||
public static final CommandContainer NULL_COMMAND = new CommandContainer(null);
|
||||
private final Command command;
|
||||
private CommandOptions commandOptions;
|
||||
|
||||
public CommandContainer(Command command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public CommandOptions getCommandOptions() {
|
||||
return commandOptions;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
initOptions();
|
||||
}
|
||||
|
||||
private void initOptions() {
|
||||
if (command != null) {
|
||||
CommandOptionsBuilder commandOptionsBuilder = new CommandOptionsBuilder(command);
|
||||
command.registerCommandOptions(commandOptionsBuilder);
|
||||
commandOptions = commandOptionsBuilder.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,18 +6,14 @@ package me.bobert.netneutrality.core.command;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.Command;
|
||||
import me.bobert.netneutrality.core.LogHandler;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
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 org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -27,25 +23,26 @@ import java.util.Set;
|
||||
public class CommandManager {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(CommandManager.class);
|
||||
public static final HashMap<String, Command> commands = new HashMap<>();
|
||||
public static final HashMap<String, CommandContainer> commands = new HashMap<>();
|
||||
|
||||
public static void init(JDA jda) {
|
||||
logger.info("Loading commands..");
|
||||
|
||||
initCommands();
|
||||
registerSlashCommands(jda);
|
||||
|
||||
logger.info("Loaded {} commands!", commands.size());
|
||||
}
|
||||
|
||||
public static Command getCommand(String commandString) {
|
||||
return commands.get(commandString);
|
||||
return getCommandContainer(commandString).getCommand();
|
||||
}
|
||||
|
||||
public static CommandContainer getCommandContainer(String commandString) {
|
||||
return commands.getOrDefault(commandString, CommandContainer.NULL_COMMAND);
|
||||
}
|
||||
|
||||
public static void initCommands() {
|
||||
Reflections reflections = new Reflections("me.bobert.netneutrality.command");
|
||||
Set<Class<? extends Command>> classes = reflections.getSubTypesOf(Command.class);
|
||||
|
||||
Set<Class<? extends Command>> classes = new Reflections("me.bobert.netneutrality.command").getSubTypesOf(Command.class);
|
||||
for (Class<? extends Command> s : classes) {
|
||||
try {
|
||||
if (Modifier.isAbstract(s.getModifiers())) {
|
||||
@@ -53,40 +50,45 @@ public class CommandManager {
|
||||
}
|
||||
|
||||
Command command = s.getConstructor().newInstance();
|
||||
|
||||
if (!command.isEnabled())
|
||||
if (!command.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command.getCommandName() == null) {
|
||||
throw new IllegalArgumentException("Command name is null");
|
||||
}
|
||||
|
||||
if (command.getDescription() == null) {
|
||||
throw new IllegalArgumentException("Command description is null");
|
||||
}
|
||||
|
||||
CommandContainer container = new CommandContainer(command);
|
||||
container.init();
|
||||
|
||||
if (!commands.containsKey(command.getCommandName())) {
|
||||
commands.put(command.getCommandName(), command);
|
||||
commands.put(command.getCommandName(), container);
|
||||
}
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||
LogHandler.log(e);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to instantiate command {}: {}", s.getSimpleName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerSlashCommands(JDA jda) {
|
||||
public static void registerSlashCommands(JDA jda) {
|
||||
CommandListUpdateAction commandListUpdateAction = jda.updateCommands();
|
||||
List<CommandData> slashCommands = new ArrayList<>();
|
||||
|
||||
for (Command command : commands.values()) {
|
||||
for (CommandContainer container : commands.values()) {
|
||||
Command command = container.getCommand();
|
||||
if (!command.isEnabled() || !command.isSlashCommand()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.debug("Registering slash command: {}", command.getCommandName());
|
||||
String description = command.getDescription();
|
||||
if (StringUtils.isBlank(description)) {
|
||||
description = "No description provided for this command";
|
||||
}
|
||||
|
||||
try {
|
||||
SlashCommandData data = Commands.slash(command.getCommandName(), description);
|
||||
SlashCommandData data = container.getCommandOptions().getSlashCommandData();
|
||||
data.setDefaultPermissions(command.getSlashCommandPermission());
|
||||
data.setGuildOnly(command.isGuildOnly());
|
||||
command.registerSlashCommandOptions(data);
|
||||
|
||||
slashCommands.add(data);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -7,15 +7,26 @@ package me.bobert.netneutrality.core.command;
|
||||
|
||||
import io.sentry.Sentry;
|
||||
import me.bobert.netneutrality.command.Command;
|
||||
import me.bobert.netneutrality.command.CommandOptions;
|
||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.LogHandler;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.exceptions.CommandExecutionException;
|
||||
import me.bobert.netneutrality.utils.UserFunction;
|
||||
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.SubcommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.function.Predicate.not;
|
||||
import static me.bobert.netneutrality.core.command.CommandExecutionResult.Result.ERROR;
|
||||
import static me.bobert.netneutrality.core.command.CommandExecutionResult.Result.NOACTION;
|
||||
|
||||
@@ -33,14 +44,16 @@ public class CommandProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
Command command = CommandManager.getCommand(context.parseCommandName());
|
||||
context.setCommand(command);
|
||||
|
||||
CommandContainer container = CommandManager.getCommandContainer(context.parseCommandName());
|
||||
Command command = container.getCommand();
|
||||
if (command == null) {
|
||||
throw new IllegalArgumentException("Context has no command");
|
||||
}
|
||||
|
||||
context.setCommand(command);
|
||||
if (command.isGuildOnly() && !context.isFromGuild()) {
|
||||
context.replyEphemeral("This command is only available in a guild");
|
||||
context.deleteMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,48 +65,144 @@ public class CommandProcessor {
|
||||
logger.info("Executing command {} on guild {}", command.getCommandName(), context.getGuild() == null ? "PrivateMessage" : context.getGuild().getId());
|
||||
configureSentry(command);
|
||||
|
||||
if (context instanceof MessageCommandContext && command.needAdmin() && !UserFunction.isAdmin(context.getGuildUser())) {
|
||||
if (!canExecute(command)) {
|
||||
context.reply("You are not powerful enough, scrub");
|
||||
return;
|
||||
}
|
||||
|
||||
if (command.canBeExecutedBy(context.getGuildUser())) {
|
||||
if (command.canBeExecutedFrom(context.getChannel())) {
|
||||
CommandExecutionResult commandExecutionResult = null;
|
||||
|
||||
if (context instanceof SlashCommandContext slashCommandContext) {
|
||||
commandExecutionResult = command.execute(slashCommandContext);
|
||||
if (!checkUsage(container.getCommandOptions())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context instanceof MessageCommandContext messageCommandContext) {
|
||||
commandExecutionResult = command.execute(messageCommandContext);
|
||||
if (!context.isValid()) {
|
||||
StringBuilder reply = new StringBuilder("Invalid arguments provided for this command:\n");
|
||||
for (Map.Entry<OptionData, String> invalid : context.getInvalidOptions()) {
|
||||
reply.append("- ").append(invalid.getKey().getName()).append(": ").append(invalid.getValue()).append("\n");
|
||||
}
|
||||
|
||||
context.reply(reply.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
CommandExecutionResult commandExecutionResult = command.execute(context);
|
||||
if (commandExecutionResult == null) {
|
||||
throw new RuntimeException("CommandExecutionResult is null");
|
||||
}
|
||||
|
||||
CommandExecutionResult.Result result = commandExecutionResult.getResult();
|
||||
String message = commandExecutionResult.getMessage();
|
||||
if (result == NOACTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message = commandExecutionResult.getMessage();
|
||||
if (result == ERROR) {
|
||||
Exception exception = commandExecutionResult.getException();
|
||||
logger.error("Error from command {}: {}", command.getCommandName(), message, exception);
|
||||
logger.error("Error from command {}: {}", command.getCommandName(), message, commandExecutionResult.getException());
|
||||
}
|
||||
|
||||
context.reply(message);
|
||||
} catch (Exception exception) {
|
||||
if (exception instanceof CommandExecutionException) {
|
||||
LogHandler.log(exception);
|
||||
}
|
||||
|
||||
LogHandler.log(new CommandExecutionException("Error during command execution", context, exception));
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: make better
|
||||
} catch (CommandExecutionException exception) {
|
||||
LogHandler.log(exception);
|
||||
} catch (Exception exception) {
|
||||
LogHandler.log(new CommandExecutionException("Error during command execution", context, exception));
|
||||
private boolean checkUsage(CommandOptions commandOptions) {
|
||||
String[] possibleCommands = Arrays.stream(context.getFullCommand().split(" ")).skip(1).toArray(String[]::new);
|
||||
if (possibleCommands.length == 0) {
|
||||
if (!commandOptions.getSubcommandGroups().isEmpty()) {
|
||||
context.reply("Invalid usage for command: missing subcommand.\n" +
|
||||
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!commandOptions.getSubcommands().isEmpty()) {
|
||||
context.reply("Invalid usage for command: missing subcommand.\n" +
|
||||
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName());
|
||||
return false;
|
||||
}
|
||||
|
||||
return checkOptions(possibleCommands, 0, commandOptions.getOptions());
|
||||
}
|
||||
|
||||
SubcommandGroupData group = commandOptions.getSubcommandGroups().stream().filter(data -> data.getName().equals(possibleCommands[0])).findFirst().orElse(null);
|
||||
if (group != null) {
|
||||
if (possibleCommands.length < 2) {
|
||||
context.reply("Invalid usage for command: missing subcommand.\n" +
|
||||
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName());
|
||||
return false; // missing subcommand
|
||||
}
|
||||
|
||||
SubcommandData subcommand = group.getSubcommands().stream().filter(data -> data.getName().equals(possibleCommands[1])).findFirst().orElse(null);
|
||||
if (subcommand != null) {
|
||||
context.setSubcommandGroup(group);
|
||||
context.setSubcommand(subcommand);
|
||||
return checkOptions(possibleCommands, 2, subcommand.getOptions());
|
||||
}
|
||||
}
|
||||
|
||||
SubcommandData subcommand = commandOptions.getSubcommands().stream().filter(data -> data.getName().equals(possibleCommands[0])).findFirst().orElse(null);
|
||||
if (subcommand != null) {
|
||||
context.setSubcommand(subcommand);
|
||||
return checkOptions(possibleCommands, 1, subcommand.getOptions());
|
||||
}
|
||||
|
||||
return checkOptions(possibleCommands, 0, commandOptions.getOptions());
|
||||
}
|
||||
|
||||
private boolean checkOptions(String[] args, int skip, List<OptionData> options) {
|
||||
if (context instanceof SlashCommandContext) {
|
||||
context.setCurrentCommandOptions(args, options);
|
||||
return true; // slash commands are validated by discord
|
||||
}
|
||||
|
||||
List<String> arguments = new ArrayList<>(Arrays.stream(args).skip(skip).toList());
|
||||
int required = options.stream().filter(OptionData::isRequired).toList().size();
|
||||
int optional = options.stream().filter(not(OptionData::isRequired)).toList().size();
|
||||
|
||||
if (arguments.size() < required) {
|
||||
context.reply("Invalid usage for command: missing one or more required arguments\n" +
|
||||
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if last option is a string, if it is then combine all remaining strings into one
|
||||
// ["@user", "you", "are", "banned"] becomes ["@user", "you are banned"]
|
||||
if (!options.isEmpty() && arguments.size() > 1) {
|
||||
OptionData last = options.get(options.size() - 1);
|
||||
if (last.getType() == OptionType.STRING) {
|
||||
List<String> lastArgs = arguments.stream().skip(options.size() -1).toList();
|
||||
arguments.removeAll(lastArgs);
|
||||
arguments.add(String.join(" ", lastArgs));
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.size() > required + optional) {
|
||||
context.reply("Invalid usage for command: too many arguments\n" +
|
||||
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName());
|
||||
return false;
|
||||
}
|
||||
|
||||
context.setCurrentCommandOptions(arguments.toArray(String[]::new), options);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canExecute(Command command) {
|
||||
if (command.canBeExecutedFrom(context.getChannel())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (context instanceof SlashCommandContext) {
|
||||
return true; // no further check since slash perms are handled by guild settings
|
||||
}
|
||||
|
||||
if (command.canBeExecutedBy(context.getGuildUser())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return command.needAdmin() && UserFunction.isAdmin(context.getGuildUser());
|
||||
}
|
||||
|
||||
private void configureSentry(Command command) {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package me.bobert.netneutrality.core.command.builder;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.Command;
|
||||
import me.bobert.netneutrality.command.CommandOptions;
|
||||
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
|
||||
|
||||
public class CommandOptionsBuilder extends CommandDataImpl {
|
||||
private final Command command;
|
||||
|
||||
public CommandOptionsBuilder(Command command) {
|
||||
super(command.getCommandName(), command.getDescription());
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public CommandOptions build() {
|
||||
//TODO: add more command types (slash, context menu), constructors are not the same so we can't extend CommandDataImpl
|
||||
return new CommandOptions(command, this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package me.bobert.netneutrality.core.command.options;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
|
||||
/**
|
||||
* This is a wrapper around {@link OptionData} that can support both slash and message commands
|
||||
*/
|
||||
public interface CommandOption {
|
||||
OptionType getType();
|
||||
|
||||
/**
|
||||
* The name of this option.
|
||||
*
|
||||
* @return The option name
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* The file uploaded for this option.
|
||||
* <br>This is represented as an {@link Message.Attachment#isEphemeral() ephemeral} attachment which will only be hosted for up to 2 weeks.
|
||||
* If you want a permanent reference, you must download it.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option {@link #getType() type} is not {@link OptionType#ATTACHMENT}
|
||||
*
|
||||
* @return {@link net.dv8tion.jda.api.entities.Message.Attachment Attachment}
|
||||
*/
|
||||
Message.Attachment getAsAttachment();
|
||||
|
||||
/**
|
||||
* The String representation of this option value.
|
||||
* <br>This will automatically convert the value to a string if the type is not {@link OptionType#STRING OptionType.STRING}.
|
||||
* <br>This will be the ID of any resolved entity such as {@link Role} or {@link Member}.
|
||||
*
|
||||
* @return The String representation of this option value
|
||||
*/
|
||||
String getAsString();
|
||||
|
||||
/**
|
||||
* The boolean value.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option is not of type {@link OptionType#BOOLEAN BOOLEAN}
|
||||
*
|
||||
* @return The boolean value
|
||||
*/
|
||||
boolean getAsBoolean();
|
||||
|
||||
/**
|
||||
* The long value for this option.
|
||||
* <br>This will be the ID of any resolved entity such as {@link Role} or {@link Member}.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option {@link #getType() type} cannot be converted to a long
|
||||
* @throws NumberFormatException
|
||||
* If this option is of type {@link OptionType#STRING STRING} and could not be parsed to a valid long value
|
||||
*
|
||||
* @return The long value
|
||||
*/
|
||||
long getAsLong();
|
||||
|
||||
/**
|
||||
* The int value for this option.
|
||||
* <br>This will be the ID of any resolved entity such as {@link Role} or {@link Member}.
|
||||
*
|
||||
* <p><b>It is highly recommended to assert int values by using {@link OptionData#setRequiredRange(long, long)}</b>
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option {@link #getType() type} cannot be converted to a long
|
||||
* @throws NumberFormatException
|
||||
* If this option is of type {@link OptionType#STRING STRING} and could not be parsed to a valid long value
|
||||
* @throws ArithmeticException
|
||||
* If the provided integer value cannot fit into a 32bit signed int
|
||||
*
|
||||
* @return The int value
|
||||
*/
|
||||
int getAsInt();
|
||||
|
||||
/**
|
||||
* The double value for this option.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option {@link #getType() type} cannot be converted to a double
|
||||
* @throws NumberFormatException
|
||||
* If this option is of type {@link OptionType#STRING STRING} and could not be parsed to a valid double value
|
||||
*
|
||||
* @return The double value
|
||||
*/
|
||||
double getAsDouble();
|
||||
|
||||
/**
|
||||
* The resolved {@link IMentionable} instance for this option value.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If the mentioned entity is not resolvable
|
||||
*
|
||||
* @return The resolved {@link IMentionable}
|
||||
*/
|
||||
IMentionable getAsMentionable();
|
||||
|
||||
/**
|
||||
* The resolved {@link Member} for this option value.
|
||||
* <br>Note that {@link OptionType#USER OptionType.USER} can also accept users that are not members of a guild, in which case this will be null!
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option is not of type {@link OptionType#USER USER} or {@link OptionType#MENTIONABLE MENTIONABLE}
|
||||
*
|
||||
* @return The resolved {@link Member}, or null
|
||||
*/
|
||||
Member getAsMember();
|
||||
|
||||
/**
|
||||
* The resolved {@link User} for this option value.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option is not of type {@link OptionType#USER USER} or
|
||||
* {@link OptionType#MENTIONABLE MENTIONABLE} without a resolved user
|
||||
*
|
||||
* @return The resolved {@link User}
|
||||
*/
|
||||
User getAsUser();
|
||||
|
||||
/**
|
||||
* The resolved {@link Role} for this option value.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option is not of type {@link OptionType#ROLE ROLE} or
|
||||
* {@link OptionType#MENTIONABLE MENTIONABLE} without a resolved role
|
||||
*
|
||||
* @return The resolved {@link Role}
|
||||
*/
|
||||
Role getAsRole();
|
||||
|
||||
/**
|
||||
* The {@link ChannelType} for the resolved channel.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option is not of type {@link OptionType#CHANNEL CHANNEL}
|
||||
*
|
||||
* @return The {@link ChannelType}
|
||||
*/
|
||||
ChannelType getChannelType();
|
||||
|
||||
/**
|
||||
* The resolved {@link net.dv8tion.jda.api.entities.channel.middleman.GuildChannel} for this option value.
|
||||
* <br>Note that {@link OptionType#CHANNEL OptionType.CHANNEL} can accept channels of any type!
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If this option is not of type {@link OptionType#CHANNEL CHANNEL}
|
||||
* or could not be resolved for unexpected reasons
|
||||
*
|
||||
* @return The resolved {@link net.dv8tion.jda.api.entities.channel.middleman.GuildChannel}
|
||||
*/
|
||||
GuildChannelUnion getAsChannel();
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package me.bobert.netneutrality.core.command.options;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
|
||||
public class MessageCommandOption implements CommandOption {
|
||||
private final OptionData data;
|
||||
private final OptionType type;
|
||||
private final Object value;
|
||||
|
||||
public MessageCommandOption(OptionData data, Object value) {
|
||||
this.data = data;
|
||||
this.type = data.getType();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptionType getType() {
|
||||
return data.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return data.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message.Attachment getAsAttachment() {
|
||||
throw new UnsupportedOperationException("Not supported for message commands");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
return switch (type) {
|
||||
case STRING -> (String) value;
|
||||
case BOOLEAN -> String.valueOf((boolean) value);
|
||||
case NUMBER -> String.valueOf((double) value);
|
||||
case MENTIONABLE -> ((IMentionable) value).getId();
|
||||
case CHANNEL -> ((GuildChannelUnion) value).getId();
|
||||
case ROLE -> ((Role) value).getId();
|
||||
case USER -> ((User) value).getId();
|
||||
case INTEGER -> String.valueOf((long) value);
|
||||
case ATTACHMENT -> ((Message.Attachment) value).getId();
|
||||
default -> throw new IllegalStateException("Cannot convert option of type " + type + " to long");
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (type != OptionType.BOOLEAN) {
|
||||
throw new IllegalStateException("Cannot convert option of type " + type + " to boolean");
|
||||
}
|
||||
|
||||
return (boolean) value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAsLong() {
|
||||
return switch (type) {
|
||||
case STRING -> Long.parseLong((String) value);
|
||||
case MENTIONABLE -> ((IMentionable) value).getIdLong();
|
||||
case CHANNEL -> ((GuildChannelUnion) value).getIdLong();
|
||||
case ROLE -> ((Role) value).getIdLong();
|
||||
case USER -> ((User) value).getIdLong();
|
||||
case INTEGER -> (long) value;
|
||||
case NUMBER -> ((Double) value).longValue();
|
||||
case ATTACHMENT -> ((Message.Attachment) value).getIdLong();
|
||||
default -> throw new IllegalStateException("Cannot convert option of type " + type + " to long");
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
return Math.toIntExact(getAsLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getAsDouble() {
|
||||
return switch (type) {
|
||||
case STRING -> Double.parseDouble((String) value);
|
||||
case NUMBER -> (double) value;
|
||||
case INTEGER -> (int) value;
|
||||
default -> throw new IllegalStateException("Cannot convert option of type " + type + " to double");
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMentionable getAsMentionable() {
|
||||
if (value instanceof IMentionable) {
|
||||
return (IMentionable) value;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot resolve option of type " + type + " to IMentionable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getAsMember() {
|
||||
if (value instanceof Member) {
|
||||
return (Member) value;
|
||||
}
|
||||
|
||||
if (value instanceof User) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot resolve option of type " + type + " to Member");
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getAsUser() {
|
||||
if (value instanceof User) {
|
||||
return (User) value;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot resolve option of type " + type + " to User");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role getAsRole() {
|
||||
if (value instanceof Role) {
|
||||
return (Role) value;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot resolve option of type " + type + " to Role");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelType getChannelType() {
|
||||
return getAsChannel().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuildChannelUnion getAsChannel() {
|
||||
if (value instanceof GuildChannelUnion) {
|
||||
return (GuildChannelUnion) value;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot resolve option of type " + type + " to GuildChannelUnion");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package me.bobert.netneutrality.core.command.options;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
|
||||
public class SlashCommandOption implements CommandOption {
|
||||
private final OptionMapping mapping;
|
||||
|
||||
public SlashCommandOption(OptionMapping mapping) {
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptionType getType() {
|
||||
return mapping.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return mapping.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message.Attachment getAsAttachment() {
|
||||
return mapping.getAsAttachment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
return mapping.getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
return mapping.getAsBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAsLong() {
|
||||
return mapping.getAsLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAsInt() {
|
||||
return mapping.getAsInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getAsDouble() {
|
||||
return mapping.getAsDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMentionable getAsMentionable() {
|
||||
return mapping.getAsMentionable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getAsMember() {
|
||||
return mapping.getAsMember();
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getAsUser() {
|
||||
return mapping.getAsUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role getAsRole() {
|
||||
return mapping.getAsRole();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelType getChannelType() {
|
||||
return mapping.getChannelType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuildChannelUnion getAsChannel() {
|
||||
return mapping.getAsChannel();
|
||||
}
|
||||
}
|
||||
@@ -6,17 +6,32 @@ package me.bobert.netneutrality.core.context;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.command.Command;
|
||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||
import me.bobert.netneutrality.utils.Settings;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class CommandContext extends AbstractContext {
|
||||
private Command command;
|
||||
private SubcommandGroupData subcommandGroup;
|
||||
private SubcommandData subcommand;
|
||||
private final Map <OptionData, String> invalidOptions = new HashMap<>();
|
||||
private final List<CommandOption> options;
|
||||
|
||||
public CommandContext(JDA jda, Guild guild, MessageChannel channel, Member member, User user) {
|
||||
super(jda, guild, channel, member, user);
|
||||
this.options = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
@@ -27,8 +42,97 @@ public abstract class CommandContext extends AbstractContext {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public void setSubcommandGroup(SubcommandGroupData subcommandGroup) {
|
||||
this.subcommandGroup = subcommandGroup;
|
||||
}
|
||||
|
||||
public void setSubcommand(SubcommandData subcommand) {
|
||||
this.subcommand = subcommand;
|
||||
}
|
||||
|
||||
public void setCurrentCommandOptions(String[] args, List<OptionData> options) {
|
||||
this.options.clear();
|
||||
this.options.addAll(parseOptions(args, options));
|
||||
}
|
||||
|
||||
protected void invalidateContext(OptionData option, String message) {
|
||||
invalidOptions.put(option, message);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return invalidOptions.isEmpty();
|
||||
}
|
||||
|
||||
public Set<Map.Entry<OptionData, String>> getInvalidOptions() {
|
||||
return invalidOptions.entrySet();
|
||||
}
|
||||
|
||||
public <T> T getOption(String name, Supplier<? extends T> fallback, Function<? super CommandOption, ? extends T> resolver) {
|
||||
Objects.requireNonNull(resolver, "resolver cannot be null");
|
||||
CommandOption mapping = getOption(name);
|
||||
if (mapping != null)
|
||||
return resolver.apply(mapping);
|
||||
return fallback == null ? null : fallback.get();
|
||||
}
|
||||
|
||||
public <T> T getOption(String name, T fallback, Function<? super CommandOption, ? extends T> resolver) {
|
||||
Objects.requireNonNull(resolver, "resolver cannot be null");
|
||||
CommandOption mapping = getOption(name);
|
||||
if (mapping != null)
|
||||
return resolver.apply(mapping);
|
||||
return fallback;
|
||||
}
|
||||
|
||||
public <T> T getOption(String name, Function<? super CommandOption, ? extends T> resolver) {
|
||||
return getOption(name, null, resolver);
|
||||
}
|
||||
|
||||
public CommandOption getOption(String name) {
|
||||
List<CommandOption> options = getOptionsByName(name);
|
||||
return options.isEmpty() ? null : options.get(0);
|
||||
}
|
||||
|
||||
public List<CommandOption> getOptionsByName(String name) {
|
||||
Objects.requireNonNull(name, "name cannot be null");
|
||||
return options.stream().filter(opt -> opt.getName().equals(name)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public String getSubcommandGroup() {
|
||||
if (subcommandGroup == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return subcommandGroup.getName();
|
||||
}
|
||||
|
||||
public String getSubcommand() {
|
||||
if (subcommand == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return subcommand.getName();
|
||||
}
|
||||
|
||||
public boolean isMessageFromOwner() {
|
||||
if (getGuildUser() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getGuildUser().isOwner();
|
||||
}
|
||||
|
||||
public boolean isMessageFromCreator() {
|
||||
String creatorId = Settings.getInstance().get("NETNEUTRALITY_BOT_OWNER");
|
||||
|
||||
return creatorId.equals(getDiscordUser().getId());
|
||||
}
|
||||
|
||||
public abstract List<CommandOption> parseOptions(String[] args, List<OptionData> commandOptions);
|
||||
|
||||
public abstract String parseCommandName();
|
||||
|
||||
public abstract String getSubCommand();
|
||||
public abstract String getFullCommand();
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -7,11 +7,10 @@ package me.bobert.netneutrality.core.context;
|
||||
|
||||
import me.bobert.netneutrality.context.AsyncContext;
|
||||
import me.bobert.netneutrality.core.GuildManager;
|
||||
import me.bobert.netneutrality.utils.ContextUtils;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.Event;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
@@ -26,6 +25,8 @@ import java.util.function.Consumer;
|
||||
public interface Context {
|
||||
Event getEvent();
|
||||
|
||||
ChannelType getType();
|
||||
|
||||
JDA getJDA();
|
||||
|
||||
InteractionHook getInteractionHook();
|
||||
@@ -73,7 +74,7 @@ public interface Context {
|
||||
}
|
||||
|
||||
default void reply(String message) {
|
||||
reply(MessageCreateData.fromContent(message));
|
||||
replyWithLimit(message);
|
||||
}
|
||||
|
||||
default void reply(MessageEmbed embed) {
|
||||
@@ -85,7 +86,7 @@ public interface Context {
|
||||
}
|
||||
|
||||
default void reply(String format, Object... arguments) {
|
||||
reply(String.format(format, arguments));
|
||||
replyWithLimit(String.format(format, arguments));
|
||||
}
|
||||
|
||||
default void edit(MessageEditData messageEditData, boolean ephemeral, List<LayoutComponent> components, Consumer<AsyncContext> consumer) {
|
||||
@@ -165,7 +166,7 @@ public interface Context {
|
||||
}
|
||||
|
||||
default void sendMessageInPrivate(String message) {
|
||||
sendMessageInPrivate(message, List.of());
|
||||
sendMessageInPrivateWithLimit(message);
|
||||
}
|
||||
|
||||
default void sendMessageInPrivate(String message, List<LayoutComponent> components) {
|
||||
@@ -179,4 +180,16 @@ public interface Context {
|
||||
default void sendMessageInPrivate(List<MessageEmbed> embeds) {
|
||||
sendMessageInPrivate(MessageCreateData.fromEmbeds(embeds));
|
||||
}
|
||||
|
||||
private void replyWithLimit(String message) {
|
||||
for (String chunk : ContextUtils.splitMessage(message, Message.MAX_CONTENT_LENGTH)) {
|
||||
reply(MessageCreateData.fromContent(chunk));
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessageInPrivateWithLimit(String message) {
|
||||
for (String chunk : ContextUtils.splitMessage(message, Message.MAX_CONTENT_LENGTH)) {
|
||||
sendMessageInPrivate(MessageCreateData.fromContent(chunk));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,19 +5,18 @@ package me.bobert.netneutrality.core.tasks;
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* Represents a task that has a known ID and is loaded at runtime.
|
||||
* This can be any task and is not necessarily a button.
|
||||
*/
|
||||
public interface BuiltInTask extends Task {
|
||||
|
||||
static TaskButtonCreator createButton(Class<? extends BuiltInTask> clazz) {
|
||||
try {
|
||||
BuiltInTask task = clazz.getConstructor().newInstance();
|
||||
return new TaskButtonCreator(task.getId());
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
BuiltInTask builtInTask = TaskManager.getInstance().getTaskMap().values().stream().filter(clazz::isInstance).map(task -> (BuiltInTask) task).findFirst().orElse(null);
|
||||
if (builtInTask == null) {
|
||||
throw new IllegalArgumentException("Task class " + clazz.getName() + " was not registered by the task manager.");
|
||||
}
|
||||
|
||||
return new TaskButtonCreator(builtInTask.getId());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
package me.bobert.netneutrality.exceptions;
|
||||
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
@@ -8,9 +7,6 @@ package me.bobert.netneutrality.exceptions;
|
||||
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
|
||||
/**
|
||||
* Logs the error internally, without sending a message
|
||||
*/
|
||||
public class CommandExecutionException extends ContextException {
|
||||
|
||||
public CommandExecutionException(String message, CommandContext context, Throwable cause) {
|
||||
|
||||
@@ -17,7 +17,7 @@ public class BotInfo extends AbstractBuiltInTask {
|
||||
|
||||
@Override
|
||||
public void execute(TaskContext context) {
|
||||
context.reply("For information about the bot and to follow the development, " +
|
||||
context.sendMessageInPrivate("For information about the bot and to follow the development, " +
|
||||
"you can join the discord here: https://discord.gg/udVJwTgV");
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ package me.bobert.netneutrality.tasks.help;
|
||||
import me.bobert.netneutrality.core.context.TaskContext;
|
||||
import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask;
|
||||
import me.bobert.netneutrality.utils.MessageFunction;
|
||||
import me.bobert.netneutrality.utils.Settings;
|
||||
|
||||
public class CommandHelp extends AbstractBuiltInTask {
|
||||
|
||||
@@ -18,6 +19,7 @@ public class CommandHelp extends AbstractBuiltInTask {
|
||||
|
||||
@Override
|
||||
public void execute(TaskContext context) {
|
||||
context.reply(MessageFunction.buildHelpMessage());
|
||||
context.replyEphemeral("The prefix for the bot is " + Settings.getInstance().getPrefix());
|
||||
context.replyEphemeral(MessageFunction.buildHelpMessage());
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ public class ReportBug extends AbstractBuiltInTask {
|
||||
|
||||
@Override
|
||||
public void execute(TaskContext context) {
|
||||
context.reply("To report a buuug with the bot, you can either use the /report-bug command " +
|
||||
context.sendMessageInPrivate("To report a bug with the bot, you can either use the /report-bug command " +
|
||||
"or join the discord here: https://discord.gg/udVJwTgV");
|
||||
}
|
||||
}
|
||||
@@ -30,10 +30,10 @@ public class MusicPlayerAutoDisconnectThread implements Runnable {
|
||||
}
|
||||
|
||||
private void processManager(MusicManager manager) throws InterruptedException {
|
||||
logger.debug("Processing MusicPlayerAutoDisconnectThread for guild {}", manager.getGuild().getId());
|
||||
AudioChannel channel = manager.getGuild().getAudioManager().getConnectedChannel();
|
||||
|
||||
if (channel != null) {
|
||||
logger.debug("Processing MusicPlayerAutoDisconnectThread for guild {}", manager.getGuild().getId());
|
||||
if (conditionsMetToDisconnect(manager)) {
|
||||
logger.debug("Guild {}: Sleeping 30 seconds and checking again", manager.getGuild().getId());
|
||||
// Sleep 30 seconds then check again (prevents disconnecting right after a track ends)
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package me.bobert.netneutrality.utils;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ContextUtils {
|
||||
|
||||
|
||||
public static List<String> splitMessage(String input, int limit) {
|
||||
List<String> chunks = new ArrayList<>();
|
||||
int index = 0;
|
||||
|
||||
while (index < input.length()) {
|
||||
// Check if the remaining text is within the limit
|
||||
if (input.length() - index <= limit) {
|
||||
chunks.add(trimTrailingNewline(input.substring(index)));
|
||||
break;
|
||||
}
|
||||
|
||||
// Determine the endpoint of the current chunk
|
||||
int endIndex = Math.min(index + limit, input.length());
|
||||
String chunk = input.substring(index, endIndex);
|
||||
|
||||
// Find the last suitable truncation boundary
|
||||
int boundaryIndex = findLastBoundary(chunk);
|
||||
|
||||
// Adjust the truncation index
|
||||
if (boundaryIndex == -1 && endIndex < input.length()) {
|
||||
// Hard truncate if no suitable boundary is found and not at the end
|
||||
boundaryIndex = limit;
|
||||
} else if (boundaryIndex > -1) {
|
||||
// Include sentence-ending punctuation if present
|
||||
boundaryIndex += 1;
|
||||
}
|
||||
|
||||
// Extract the chunk and trim unnecessary trailing '\n'
|
||||
endIndex = index + (boundaryIndex > -1 ? boundaryIndex : limit);
|
||||
String trimmedChunk = trimTrailingNewline(input.substring(index, endIndex));
|
||||
|
||||
// Add the chunk to the result list
|
||||
chunks.add(trimmedChunk);
|
||||
|
||||
// Move the index to the next chunk, skipping redundant newlines
|
||||
index = endIndex;
|
||||
while (index < input.length() && input.charAt(index) == '\n') {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
private static int findLastBoundary(String chunk) {
|
||||
// Find the last sentence-ending punctuation or space within the chunk
|
||||
int lastSentenceBoundary = Math.max(
|
||||
Math.max(chunk.lastIndexOf("."), Math.max(chunk.lastIndexOf("!"), chunk.lastIndexOf("?"))),
|
||||
chunk.lastIndexOf("\n")
|
||||
);
|
||||
int lastSpace = chunk.lastIndexOf(" ");
|
||||
return Math.max(lastSentenceBoundary, lastSpace);
|
||||
}
|
||||
|
||||
private static String trimTrailingNewline(String chunk) {
|
||||
// Trim trailing '\n' if present
|
||||
if (chunk.endsWith("\n")) {
|
||||
return chunk.substring(0, chunk.length() - 1).trim();
|
||||
}
|
||||
|
||||
return chunk.trim();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
||||
import io.sentry.Sentry;
|
||||
import me.bobert.netneutrality.command.Command;
|
||||
import me.bobert.netneutrality.command.CommandType;
|
||||
import me.bobert.netneutrality.core.command.CommandContainer;
|
||||
import me.bobert.netneutrality.core.command.CommandManager;
|
||||
import me.bobert.netneutrality.core.context.CommandContext;
|
||||
import me.bobert.netneutrality.core.context.Context;
|
||||
@@ -24,7 +25,6 @@ import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import org.apache.commons.lang3.time.DurationFormatUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -203,7 +203,8 @@ public class MessageFunction {
|
||||
public static String buildHelpMessage() {
|
||||
Map<CommandType, String> help = new HashMap<>();
|
||||
|
||||
for (Command command : CommandManager.commands.values()) {
|
||||
for (CommandContainer container : CommandManager.commands.values()) {
|
||||
Command command = container.getCommand();
|
||||
if (command.getType() == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -233,19 +234,19 @@ public class MessageFunction {
|
||||
|
||||
String subtext = "\n\n" +
|
||||
"-# The bot supports both types of commands: slash (/) and message ($), " +
|
||||
"however not all slash commands might have a corresponding message command." +
|
||||
"however not all slash commands might have a corresponding message command.\n" +
|
||||
"-# To get help for a specific command, please use /help <command> ";
|
||||
|
||||
return String.join("\n", help.values()) + subtext;
|
||||
}
|
||||
|
||||
public static String buildCommandHelpMessage(Command command) {
|
||||
String message = "## Command info for /" + command.getCommandName();
|
||||
if (command.getDescription() != null) {
|
||||
message += "\n- Description: " + command.getDescription();
|
||||
}
|
||||
public static String buildCommandHelpMessage(CommandContainer container) {
|
||||
|
||||
message += "\n\n-# *: required argument";
|
||||
String message = "## Command info for /" + container.getCommand().getCommandName();
|
||||
if (container.getCommand().getDescription() != null) {
|
||||
message += "\n- Description: " + container.getCommand().getDescription();
|
||||
}
|
||||
message += "\n" + container.getCommandOptions().printUsage();
|
||||
|
||||
return message;
|
||||
}
|
||||
@@ -280,7 +281,7 @@ public class MessageFunction {
|
||||
if (exception.getCause() != null) {
|
||||
String cause;
|
||||
if (exception.getCause().getMessage() != null && !exception.getCause().getMessage().isEmpty()) {
|
||||
cause = exception.getCause().getMessage().substring(0, 64);
|
||||
cause = exception.getCause().getMessage().substring(0, Math.min(exception.getCause().getMessage().length(), 64));
|
||||
} else {
|
||||
cause = exception.getCause().getClass().getName();
|
||||
}
|
||||
@@ -316,19 +317,4 @@ public class MessageFunction {
|
||||
return editEmbed.build();
|
||||
}
|
||||
|
||||
public static void testMessageAgainstBlacklist(Message message, MessageChannel channel, Set<String> cache) {
|
||||
boolean found = false;
|
||||
for (String word : cache) {
|
||||
if (message.getContentRaw().toLowerCase().contains(word)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
message.delete().queue();
|
||||
channel.sendMessage("Not in my christian server").queue();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package me.bobert.netneutrality.utils;
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.context.MusicChannelContext;
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.context.Context;
|
||||
import me.bobert.netneutrality.exceptions.ContextException;
|
||||
import me.bobert.netneutrality.music.MusicManager;
|
||||
@@ -87,6 +88,14 @@ public class MusicUtils {
|
||||
return memberVoiceState.getChannel();
|
||||
}
|
||||
|
||||
public static boolean isUserDj(Context context) {
|
||||
if (context instanceof SlashCommandContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isUserDj(context.getGuildUser());
|
||||
}
|
||||
|
||||
public static boolean isUserDj(Member member) {
|
||||
MusicManager manager = MusicManager.get(member.getGuild());
|
||||
Member dj = manager.getScheduler().getDj();
|
||||
|
||||
@@ -6,12 +6,22 @@ package me.bobert.netneutrality.utils;
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||
import me.bobert.netneutrality.core.context.Context;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
|
||||
public class UserFunction {
|
||||
|
||||
public static boolean isAdmin(Context context) {
|
||||
if (context instanceof SlashCommandContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isAdmin(context.getGuildUser());
|
||||
}
|
||||
|
||||
public static boolean isAdmin(Member user) {
|
||||
boolean isAdmin = false;
|
||||
for(Role role : user.getRoles()) {
|
||||
|
||||
Reference in new issue
Block a user