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
+1461
-710
No files matched your search
@@ -69,10 +69,11 @@ public class NetNeutrality {
|
|||||||
private void startup() {
|
private void startup() {
|
||||||
// DatabaseMigration.migrate();
|
// DatabaseMigration.migrate();
|
||||||
SessionManager.getSessionFactory();
|
SessionManager.getSessionFactory();
|
||||||
initJDA();
|
|
||||||
CommandManager.init(jda);
|
CommandManager.init(jda);
|
||||||
MusicManager.initPlayerManager();
|
MusicManager.initPlayerManager();
|
||||||
TaskManager.getInstance().init();
|
TaskManager.getInstance().init();
|
||||||
|
initJDA();
|
||||||
|
CommandManager.registerSlashCommands(jda);
|
||||||
jda.addEventListener(new ServerJoinHook());
|
jda.addEventListener(new ServerJoinHook());
|
||||||
jda.addEventListener(new MessageReceivedHook(), new SlashCommandHook());
|
jda.addEventListener(new MessageReceivedHook(), new SlashCommandHook());
|
||||||
jda.addEventListener(new ModalInteractionHook(), new ButtonInteractionHook(), new EmojiReactionHook());
|
jda.addEventListener(new ModalInteractionHook(), new ButtonInteractionHook(), new EmojiReactionHook());
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ package me.bobert.netneutrality.command;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* 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.Member;
|
||||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||||
@@ -34,11 +31,4 @@ public abstract class AbstractCommand implements Command {
|
|||||||
public boolean canBeExecutedFrom(MessageChannel channel) {
|
public boolean canBeExecutedFrom(MessageChannel channel) {
|
||||||
return true;
|
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
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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.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.Member;
|
||||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public interface Command {
|
public interface Command {
|
||||||
|
|
||||||
@@ -28,9 +26,9 @@ public interface Command {
|
|||||||
|
|
||||||
String getDescription();
|
String getDescription();
|
||||||
|
|
||||||
DefaultMemberPermissions getSlashCommandPermission();
|
void registerCommandOptions(CommandOptionsBuilder builder);
|
||||||
|
|
||||||
void registerSlashCommandOptions(SlashCommandData data);
|
DefaultMemberPermissions getSlashCommandPermission();
|
||||||
|
|
||||||
CommandType getType();
|
CommandType getType();
|
||||||
|
|
||||||
@@ -38,8 +36,5 @@ public interface Command {
|
|||||||
|
|
||||||
boolean canBeExecutedFrom(MessageChannel channel);
|
boolean canBeExecutedFrom(MessageChannel channel);
|
||||||
|
|
||||||
@Deprecated
|
CommandExecutionResult execute(CommandContext context);
|
||||||
CommandExecutionResult execute(MessageCommandContext context);
|
|
||||||
|
|
||||||
CommandExecutionResult execute(SlashCommandContext 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.command.AbstractAdminCommand;
|
||||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
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.entities.OBlacklist;
|
||||||
import me.bobert.netneutrality.db.repository.BlacklistRepository;
|
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.OptionType;
|
||||||
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.SubcommandData;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -41,25 +40,20 @@ public class BlacklistCommand extends AbstractAdminCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
data.addSubcommands(
|
builder.addSubcommands(
|
||||||
new SubcommandData("get", "Get all blacklisted words for this guild"),
|
new SubcommandData("get", "Get all blacklisted words for this guild"),
|
||||||
new SubcommandData("add", "Add a word to the blacklist")
|
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")
|
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
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
return CommandExecutionResult.none();
|
String sub = context.getSubcommand();
|
||||||
}
|
String word = context.getOption("word", "", CommandOption::getAsString);
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
|
||||||
String sub = context.getEvent().getFullCommandName().split(" ")[1];
|
|
||||||
String word = context.getEvent().getOption("word", "", OptionMapping::getAsString);
|
|
||||||
BlacklistRepository repository = new BlacklistRepository();
|
BlacklistRepository repository = new BlacklistRepository();
|
||||||
|
|
||||||
switch (sub) {
|
switch (sub) {
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ package me.bobert.netneutrality.command.admin;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractAdminCommand;
|
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.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.core.tasks.TaskManager;
|
||||||
import me.bobert.netneutrality.tasks.emoji.EmojiReactionRoleTask;
|
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.OptionType;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
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.SubcommandData;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
|
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ public class ReactionCommand extends AbstractAdminCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
data.addSubcommandGroups(
|
builder.addSubcommandGroups(
|
||||||
new SubcommandGroupData("emoji", "Give roles to users using emojis").addSubcommands(
|
new SubcommandGroupData("emoji", "Give roles to users using emojis").addSubcommands(
|
||||||
new SubcommandData("setup", "Add a role to a message").addOptions(
|
new SubcommandData("setup", "Add a role to a message").addOptions(
|
||||||
new OptionData(OptionType.STRING, "messageid", "The ID of the message", true),
|
new OptionData(OptionType.STRING, "messageid", "The ID of the message", true),
|
||||||
@@ -65,19 +65,19 @@ public class ReactionCommand extends AbstractAdminCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
context.ack();
|
context.ack();
|
||||||
|
|
||||||
String guildId = context.getGuild().getId();
|
String guildId = context.getGuild().getId();
|
||||||
String messageId = context.getEvent().getOption("messageid", OptionMapping::getAsString);
|
String messageId = context.getOption("messageid", CommandOption::getAsString);
|
||||||
String sub = context.getSubCommand();
|
String group = context.getSubcommandGroup();
|
||||||
String action = context.getEvent().getFullCommandName().split(" ")[2];
|
String sub = context.getSubcommand();
|
||||||
|
|
||||||
switch (sub) {
|
switch (group) {
|
||||||
case "emoji" -> {
|
case "emoji" -> {
|
||||||
if ("setup".equals(action)) {
|
if ("setup".equals(sub)) {
|
||||||
String emoji = context.getEvent().getOption("emoji", OptionMapping::getAsString);
|
String emoji = context.getOption("emoji", CommandOption::getAsString);
|
||||||
String role = context.getEvent().getOption("role", OptionMapping::getAsString);
|
String role = context.getOption("role", CommandOption::getAsString);
|
||||||
|
|
||||||
EmojiReactionRoleTask task = new EmojiReactionRoleTask(guildId, messageId);
|
EmojiReactionRoleTask task = new EmojiReactionRoleTask(guildId, messageId);
|
||||||
if (TaskManager.getInstance().exists(task.getId())) {
|
if (TaskManager.getInstance().exists(task.getId())) {
|
||||||
@@ -89,9 +89,9 @@ public class ReactionCommand extends AbstractAdminCommand {
|
|||||||
return CommandExecutionResult.success("Added emoji to message successfully!");
|
return CommandExecutionResult.success("Added emoji to message successfully!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("add".equals(action)) {
|
if ("add".equals(sub)) {
|
||||||
String emoji = context.getEvent().getOption("emoji", OptionMapping::getAsString);
|
String emoji = context.getOption("emoji", CommandOption::getAsString);
|
||||||
String role = context.getEvent().getOption("role", OptionMapping::getAsString);
|
String role = context.getOption("role", CommandOption::getAsString);
|
||||||
|
|
||||||
String id = String.format("%s:%s", guildId, messageId);
|
String id = String.format("%s:%s", guildId, messageId);
|
||||||
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
||||||
@@ -104,8 +104,8 @@ public class ReactionCommand extends AbstractAdminCommand {
|
|||||||
return CommandExecutionResult.success("Added emoji to message successfully!");
|
return CommandExecutionResult.success("Added emoji to message successfully!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("remove".equals(action)) {
|
if ("remove".equals(sub)) {
|
||||||
String emoji = context.getEvent().getOption("emoji", OptionMapping::getAsString);
|
String emoji = context.getOption("emoji", CommandOption::getAsString);
|
||||||
|
|
||||||
String id = String.format("%s:%s", guildId, messageId);
|
String id = String.format("%s:%s", guildId, messageId);
|
||||||
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
||||||
@@ -118,7 +118,7 @@ public class ReactionCommand extends AbstractAdminCommand {
|
|||||||
return CommandExecutionResult.success("Removed emoji from message successfully!");
|
return CommandExecutionResult.success("Removed emoji from message successfully!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("delete".equals(action)) {
|
if ("delete".equals(sub)) {
|
||||||
String id = String.format("%s:%s", guildId, messageId);
|
String id = String.format("%s:%s", guildId, messageId);
|
||||||
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
EmojiReactionRoleTask task = (EmojiReactionRoleTask) TaskManager.getInstance().getTask(id);
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
|
|||||||
@@ -6,24 +6,21 @@ package me.bobert.netneutrality.command.basic;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractCommand;
|
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.command.CommandType;
|
||||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
import me.bobert.netneutrality.core.command.CommandContainer;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||||
import me.bobert.netneutrality.core.command.CommandManager;
|
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.core.tasks.BuiltInTask;
|
||||||
import me.bobert.netneutrality.tasks.help.BotInfo;
|
import me.bobert.netneutrality.tasks.help.BotInfo;
|
||||||
import me.bobert.netneutrality.tasks.help.CommandHelp;
|
import me.bobert.netneutrality.tasks.help.CommandHelp;
|
||||||
import me.bobert.netneutrality.tasks.help.ReportBug;
|
import me.bobert.netneutrality.tasks.help.ReportBug;
|
||||||
import me.bobert.netneutrality.utils.MessageFunction;
|
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.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.ActionRow;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||||
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -55,9 +52,8 @@ public class HelpCommand extends AbstractCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
builder.addOption(OptionType.STRING, "command", "The name of the command you want help with", false);
|
||||||
data.addOption(OptionType.STRING, "command", "The name of the command you want help with", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -66,37 +62,25 @@ public class HelpCommand extends AbstractCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
context.reply(new MessageCreateBuilder().addContent(context.getDiscordUser().getAsMention()).addContent(" help has been sent your way!").build());
|
String command = context.getOption("command", null, CommandOption::getAsString);
|
||||||
sendHelp(context, context.getArgument(0));
|
if (command == null) {
|
||||||
|
|
||||||
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) {
|
|
||||||
Button commands = BuiltInTask.createButton(CommandHelp.class).primary("Commands");
|
Button commands = BuiltInTask.createButton(CommandHelp.class).primary("Commands");
|
||||||
Button info = BuiltInTask.createButton(BotInfo.class).primary("Info");
|
Button info = BuiltInTask.createButton(BotInfo.class).primary("Info");
|
||||||
Button reportbug = BuiltInTask.createButton(ReportBug.class).danger("Report bug");
|
Button reportbug = BuiltInTask.createButton(ReportBug.class).danger("Report bug");
|
||||||
ActionRow row = ActionRow.of(commands, info, reportbug);
|
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));
|
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);
|
CommandContainer container = CommandManager.getCommandContainer(command);
|
||||||
if (command == null) {
|
if (container.getCommand() == null) {
|
||||||
context.reply("Command does not exist");
|
return CommandExecutionResult.warn("Command does not exist");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.AbstractCommand;
|
||||||
import me.bobert.netneutrality.command.CommandType;
|
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.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 {
|
public class PingCommand extends AbstractCommand {
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ public class PingCommand extends AbstractCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,15 +49,7 @@ public class PingCommand extends AbstractCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
if (context.getArgs().isEmpty())
|
|
||||||
context.reply(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing()));
|
|
||||||
|
|
||||||
return CommandExecutionResult.none();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
|
||||||
return CommandExecutionResult.success(String.format("Pong! [%d ms]", context.getJDA().getGatewayPing()));
|
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.command.AbstractAdminCommand;
|
||||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
|
||||||
import me.bobert.netneutrality.core.GuildManager;
|
import me.bobert.netneutrality.core.GuildManager;
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
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.db.GSettings;
|
||||||
import me.bobert.netneutrality.music.MusicManager;
|
import me.bobert.netneutrality.music.MusicManager;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
|
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.OptionType;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
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.SubcommandData;
|
||||||
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ConfigureCommand extends AbstractAdminCommand {
|
public class ConfigureCommand extends AbstractAdminCommand {
|
||||||
@@ -48,11 +46,11 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
data.addSubcommands(
|
builder.addSubcommands(
|
||||||
new SubcommandData("music-volume", "Volume for the music player")
|
new SubcommandData("music-volume", "Volume for the music player")
|
||||||
.addOptions(new OptionData(OptionType.INTEGER, "volume", "Integer between 0 and 100", true)
|
.addOptions(new OptionData(OptionType.INTEGER, "volume", "Integer between 0 and 100", true)
|
||||||
.setRequiredRange(0, 100)),
|
.setRequiredRange(0, 100)),
|
||||||
new SubcommandData("error-logging", "Send errors to #error and/or #log channel")
|
new SubcommandData("error-logging", "Send errors to #error and/or #log channel")
|
||||||
.addOption(OptionType.BOOLEAN, "debug", "Enable or disable the fonctionnality", true),
|
.addOption(OptionType.BOOLEAN, "debug", "Enable or disable the fonctionnality", true),
|
||||||
new SubcommandData("music-role", "Role needed to use music commands")
|
new SubcommandData("music-role", "Role needed to use music commands")
|
||||||
@@ -63,143 +61,13 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
Map<Integer, String> args = context.getArgs();
|
String sub = context.getSubcommand();
|
||||||
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];
|
|
||||||
GuildManager guildManager = GuildManager.getManager(context.getGuild());
|
GuildManager guildManager = GuildManager.getManager(context.getGuild());
|
||||||
context.ephemeral();
|
context.ephemeral();
|
||||||
|
|
||||||
if ("music-role".equals(sub)) {
|
if ("music-role".equals(sub)) {
|
||||||
Role role = context.getEvent().getOption("role", OptionMapping::getAsRole);
|
Role role = context.getOption("role", CommandOption::getAsRole);
|
||||||
assert role != null;
|
assert role != null;
|
||||||
|
|
||||||
if (role.getPosition() == -1) {
|
if (role.getPosition() == -1) {
|
||||||
@@ -216,7 +84,7 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("music-channel".equals(sub)) {
|
if ("music-channel".equals(sub)) {
|
||||||
GuildChannelUnion channel = context.getEvent().getOption("channel", OptionMapping::getAsChannel);
|
GuildChannelUnion channel = context.getOption("channel", CommandOption::getAsChannel);
|
||||||
|
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_CHANNEL, null);
|
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_CHANNEL, null);
|
||||||
@@ -235,7 +103,7 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("music-volume".equals(sub)) {
|
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));
|
guildManager.getGuildConfigManager().setSettingValue(GSettings.MUSIC_VOLUME, String.valueOf(volume));
|
||||||
MusicManager.get(context.getGuild()).setVolume(volume);
|
MusicManager.get(context.getGuild()).setVolume(volume);
|
||||||
|
|
||||||
@@ -243,7 +111,7 @@ public class ConfigureCommand extends AbstractAdminCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("error-logging".equals(sub)) {
|
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);
|
guildManager.setDebug(debug);
|
||||||
|
|
||||||
return CommandExecutionResult.success("Error logging is now %s for this guild", (debug ? "enabled" : "disabled"));
|
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.command.AbstractCommand;
|
||||||
|
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||||
import me.bobert.netneutrality.command.CommandType;
|
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.LogHandler;
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
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 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.OptionType;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.Currency;
|
import java.util.Currency;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class CryptoPriceCommand extends AbstractCommand {
|
public class CryptoPriceCommand extends AbstractCommand {
|
||||||
|
|
||||||
@@ -53,9 +51,9 @@ public class CryptoPriceCommand extends AbstractCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
data.addOption(OptionType.STRING, "symbol", "The crypto symbol to fetch price for", true);
|
builder.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");
|
builder.addOption(OptionType.STRING, "currency", "In which currency should the price be displayed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -64,59 +62,13 @@ public class CryptoPriceCommand extends AbstractCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext 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;
|
|
||||||
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");
|
Locale usa = new Locale("en", "US");
|
||||||
NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
|
NumberFormat dollarFormat = NumberFormat.getCurrencyInstance(usa);
|
||||||
dollarFormat.setMaximumFractionDigits(24);
|
dollarFormat.setMaximumFractionDigits(24);
|
||||||
|
|
||||||
String symbol = context.getEvent().getOption("symbol", OptionMapping::getAsString);
|
String symbol = context.getOption("symbol", CommandOption::getAsString);
|
||||||
String currency = context.getEvent().getOption("currency", "USD", OptionMapping::getAsString);
|
String currency = context.getOption("currency", "USD", CommandOption::getAsString).toUpperCase();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
currency = Currency.getInstance(currency).getCurrencyCode();
|
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.AbstractCommand;
|
||||||
import me.bobert.netneutrality.command.CommandType;
|
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.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.core.tasks.TaskManager;
|
||||||
import me.bobert.netneutrality.tasks.git.ReportIssueTask;
|
import me.bobert.netneutrality.tasks.git.ReportIssueTask;
|
||||||
import me.bobert.netneutrality.utils.Settings;
|
import me.bobert.netneutrality.utils.Settings;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class ReportIssueCommand extends AbstractCommand {
|
public class ReportIssueCommand extends AbstractCommand {
|
||||||
@Override
|
@Override
|
||||||
@@ -41,7 +41,7 @@ public class ReportIssueCommand extends AbstractCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ public class ReportIssueCommand extends AbstractCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
String gitlabHost = Settings.getInstance().get("GITLAB_HOST");
|
String gitlabHost = Settings.getInstance().get("GITLAB_HOST");
|
||||||
String gitlabToken = Settings.getInstance().get("GITLAB_TOKEN");
|
String gitlabToken = Settings.getInstance().get("GITLAB_TOKEN");
|
||||||
String projectId = Settings.getInstance().get("GITLAB_PROJECT_ID");
|
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.AbstractMusicCommand;
|
||||||
import me.bobert.netneutrality.command.CommandType;
|
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.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.music.MusicManager;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class BitconnectCommand extends AbstractMusicCommand {
|
public class BitconnectCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ public class BitconnectCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,18 +41,10 @@ public class BitconnectCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext 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) {
|
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
context.ephemeral();
|
context.ephemeral();
|
||||||
|
context.deleteMessage();
|
||||||
|
|
||||||
manager.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, true);
|
manager.play("https://www.youtube.com/watch?v=e5nyQmaq4k4", context, true);
|
||||||
return CommandExecutionResult.success("Ready to invest?");
|
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.command.AbstractMusicCommand;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class ClearQueueCommand extends AbstractMusicCommand {
|
public class ClearQueueCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -36,12 +36,12 @@ public class ClearQueueCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
context.ack();
|
context.ack();
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,12 @@ package me.bobert.netneutrality.command.music;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
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.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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MessageFunction;
|
import me.bobert.netneutrality.utils.MessageFunction;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class CurrentlyPlayingCommand extends AbstractMusicCommand {
|
public class CurrentlyPlayingCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -33,27 +32,12 @@ public class CurrentlyPlayingCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
// no arguments
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext 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) {
|
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
context.ack();
|
context.ack();
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ package me.bobert.netneutrality.command.music;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
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.CommandExecutionResult;
|
||||||
|
import me.bobert.netneutrality.core.command.builder.CommandOptionsBuilder;
|
||||||
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class JoinCommand extends AbstractMusicCommand {
|
public class JoinCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -31,21 +30,12 @@ public class JoinCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
if (MusicUtils.connect(context)) {
|
|
||||||
context.reply("Joining current voice channel");
|
|
||||||
}
|
|
||||||
|
|
||||||
return CommandExecutionResult.none();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
|
||||||
if (MusicUtils.connect(context)) {
|
if (MusicUtils.connect(context)) {
|
||||||
context.reply("Joining current voice channel");
|
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.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.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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class LeaveCommand extends AbstractMusicCommand {
|
public class LeaveCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -32,24 +31,12 @@ public class LeaveCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext 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) {
|
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
|
|
||||||
if (MusicUtils.checkIfConnected(context)) {
|
if (MusicUtils.checkIfConnected(context)) {
|
||||||
|
|||||||
@@ -7,13 +7,12 @@ package me.bobert.netneutrality.command.music;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
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.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.OptionType;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class PlayCommand extends AbstractMusicCommand {
|
public class PlayCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -33,26 +32,14 @@ public class PlayCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
data.addOption(OptionType.STRING, "query", "URL or search query", true);
|
builder.addOption(OptionType.STRING, "query", "URL or search query", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
|
String query = context.getOption("query", CommandOption::getAsString);
|
||||||
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);
|
|
||||||
context.ack();
|
context.ack();
|
||||||
|
|
||||||
manager.play(query, context);
|
manager.play(query, context);
|
||||||
|
|||||||
@@ -6,17 +6,17 @@ package me.bobert.netneutrality.command.music;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
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.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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MessageFunction;
|
import me.bobert.netneutrality.utils.MessageFunction;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
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.OptionType;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
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.SubcommandData;
|
||||||
|
|
||||||
public class QueueCommand extends AbstractMusicCommand {
|
public class QueueCommand extends AbstractMusicCommand {
|
||||||
@@ -37,14 +37,8 @@ public class QueueCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DefaultMemberPermissions getSlashCommandPermission() {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
return DefaultMemberPermissions.DISABLED;
|
builder.addSubcommands(
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
|
||||||
|
|
||||||
data.addSubcommands(
|
|
||||||
new SubcommandData("clear-all", "Clear all queued tracks"),
|
new SubcommandData("clear-all", "Clear all queued tracks"),
|
||||||
new SubcommandData("delete-track", "Remove a single track from the queue")
|
new SubcommandData("delete-track", "Remove a single track from the queue")
|
||||||
.addOptions(new OptionData(OptionType.INTEGER, "position", "Position of track", true)
|
.addOptions(new OptionData(OptionType.INTEGER, "position", "Position of track", true)
|
||||||
@@ -59,9 +53,14 @@ public class QueueCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
public DefaultMemberPermissions getSlashCommandPermission() {
|
||||||
|
return DefaultMemberPermissions.DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
String sub = context.getSubCommand();
|
String sub = context.getSubcommand();
|
||||||
context.ack();
|
context.ack();
|
||||||
|
|
||||||
if (MusicUtils.checkIfConnected(context)) {
|
if (MusicUtils.checkIfConnected(context)) {
|
||||||
@@ -72,7 +71,7 @@ public class QueueCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "delete-track" -> {
|
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);
|
return manager.getQueueManager().removeFromQueue(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +82,7 @@ public class QueueCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "from-user" -> {
|
case "from-user" -> {
|
||||||
Member user = context.getEvent().getOption("user", OptionMapping::getAsMember);
|
Member user = context.getOption("user", CommandOption::getAsMember);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
return CommandExecutionResult.warn("The user isn't from this guild");
|
return CommandExecutionResult.warn("The user isn't from this guild");
|
||||||
}
|
}
|
||||||
@@ -92,7 +91,7 @@ public class QueueCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "remove-from-user" -> {
|
case "remove-from-user" -> {
|
||||||
Member member = context.getEvent().getOption("user", OptionMapping::getAsMember);
|
Member member = context.getOption("user", CommandOption::getAsMember);
|
||||||
if (member == null) {
|
if (member == null) {
|
||||||
return CommandExecutionResult.warn("The user isn't from this guild");
|
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.command.AbstractMusicCommand;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class ResumeCommand extends AbstractMusicCommand {
|
public class ResumeCommand extends AbstractMusicCommand {
|
||||||
@Override
|
@Override
|
||||||
@@ -28,12 +28,12 @@ public class ResumeCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
|
|
||||||
if (MusicUtils.checkIfConnected(context)) {
|
if (MusicUtils.checkIfConnected(context)) {
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ package me.bobert.netneutrality.command.music;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
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.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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class ShuffleCommand extends AbstractMusicCommand {
|
public class ShuffleCommand extends AbstractMusicCommand {
|
||||||
@Override
|
@Override
|
||||||
@@ -30,12 +30,12 @@ public class ShuffleCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
context.ack();
|
context.ack();
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ package me.bobert.netneutrality.command.music;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import me.bobert.netneutrality.utils.UserFunction;
|
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.OptionType;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class SkipCommand extends AbstractMusicCommand {
|
public class SkipCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -36,45 +35,23 @@ public class SkipCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
data.addOptions(new OptionData(OptionType.INTEGER, "skip", "Number of tracks to skip")
|
builder.addOptions(new OptionData(OptionType.INTEGER, "skip", "Number of tracks to skip")
|
||||||
.setMinValue(1));
|
.setMinValue(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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())) {
|
|
||||||
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) {
|
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
context.ack();
|
context.ack();
|
||||||
|
|
||||||
if (MusicUtils.checkIfConnected(context)) {
|
if (MusicUtils.checkIfConnected(context)) {
|
||||||
int skips = context.getEvent().getOption("skip", 1, OptionMapping::getAsInt);
|
int skips = context.getOption("skip", 1, CommandOption::getAsInt);
|
||||||
return manager.getQueueManager().skip(skips);
|
if (UserFunction.isAdmin(context) || MusicUtils.isUserDj(context)) {
|
||||||
|
return manager.getQueueManager().skip(skips);
|
||||||
|
} else {
|
||||||
|
return manager.voteSkip(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandExecutionResult.none();
|
return CommandExecutionResult.none();
|
||||||
|
|||||||
@@ -7,13 +7,12 @@ package me.bobert.netneutrality.command.music;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
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.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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import me.bobert.netneutrality.utils.UserFunction;
|
import me.bobert.netneutrality.utils.UserFunction;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class StopCommand extends AbstractMusicCommand {
|
public class StopCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -33,17 +32,17 @@ public class StopCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
|
context.ack();
|
||||||
|
|
||||||
if (MusicUtils.checkIfConnected(context)) {
|
if (MusicUtils.checkIfConnected(context)) {
|
||||||
// Need a resume command before
|
if (UserFunction.isAdmin(context)) {
|
||||||
if (UserFunction.isAdmin(context.getGuildUser())) {
|
|
||||||
manager.stopTrack();
|
manager.stopTrack();
|
||||||
context.reply("Stopping current track");
|
context.reply("Stopping current track");
|
||||||
}
|
}
|
||||||
@@ -51,17 +50,4 @@ public class StopCommand extends AbstractMusicCommand {
|
|||||||
|
|
||||||
return CommandExecutionResult.none();
|
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.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.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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MessageFunction;
|
import me.bobert.netneutrality.utils.MessageFunction;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class ViewQueueCommand extends AbstractMusicCommand {
|
public class ViewQueueCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -32,28 +31,12 @@ public class ViewQueueCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext 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) {
|
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
context.ack();
|
context.ack();
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ package me.bobert.netneutrality.command.music;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
import me.bobert.netneutrality.command.AbstractMusicCommand;
|
||||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import me.bobert.netneutrality.utils.UserFunction;
|
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.OptionType;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class VolumeCommand extends AbstractMusicCommand {
|
public class VolumeCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -36,46 +35,23 @@ public class VolumeCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
data.addOptions(new OptionData(OptionType.INTEGER, "volume", "Playback volume for this session", true)
|
builder.addOptions(new OptionData(OptionType.INTEGER, "volume", "Playback volume for this session", true)
|
||||||
.setRequiredRange(0, 100));
|
.setRequiredRange(0, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
|
int volume = context.getOption("volume", 30, CommandOption::getAsInt);
|
||||||
|
|
||||||
if (!MusicUtils.checkIfConnected(context))
|
if (MusicUtils.checkIfConnected(context)) {
|
||||||
return CommandExecutionResult.none();
|
if (UserFunction.isAdmin(context) || MusicUtils.isUserDj(context)) {
|
||||||
|
manager.setVolume(volume);
|
||||||
if (UserFunction.isAdmin(context.getGuildUser()) || MusicUtils.isUserDj(context.getGuildUser())) {
|
return CommandExecutionResult.success(String.format("Volume set to %s", volume));
|
||||||
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();
|
return CommandExecutionResult.none();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
|
||||||
int volume = context.getEvent().getOption("volume", 30, OptionMapping::getAsInt);
|
|
||||||
|
|
||||||
if (MusicUtils.checkIfConnected(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.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.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.music.MusicManager;
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|
||||||
|
|
||||||
public class VoteSkipCommand extends AbstractMusicCommand {
|
public class VoteSkipCommand extends AbstractMusicCommand {
|
||||||
|
|
||||||
@@ -31,23 +30,12 @@ public class VoteSkipCommand extends AbstractMusicCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerSlashCommandOptions(SlashCommandData data) {
|
public void registerCommandOptions(CommandOptionsBuilder builder) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandExecutionResult execute(MessageCommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
|
||||||
|
|
||||||
if (MusicUtils.checkIfConnected(context)) {
|
|
||||||
return manager.voteSkip(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return CommandExecutionResult.none();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandExecutionResult execute(SlashCommandContext context) {
|
|
||||||
MusicManager manager = MusicManager.get(context.getGuild());
|
MusicManager manager = MusicManager.get(context.getGuild());
|
||||||
|
|
||||||
if (MusicUtils.checkIfConnected(context)) {
|
if (MusicUtils.checkIfConnected(context)) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.context;
|
|||||||
|
|
||||||
import me.bobert.netneutrality.core.context.AbstractContext;
|
import me.bobert.netneutrality.core.context.AbstractContext;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
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.events.Event;
|
||||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||||
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
|
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
|
||||||
@@ -38,6 +39,11 @@ public class AsyncContext extends AbstractContext {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelType getType() {
|
||||||
|
return ChannelType.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InteractionHook getInteractionHook() {
|
public InteractionHook getInteractionHook() {
|
||||||
return hook;
|
return hook;
|
||||||
@@ -59,7 +65,7 @@ public class AsyncContext extends AbstractContext {
|
|||||||
hook.deleteOriginal().queue();
|
hook.deleteOriginal().queue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message != null) {
|
if (message != null && getType() != ChannelType.PRIVATE) {
|
||||||
message.delete().queue();
|
message.delete().queue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,18 +5,26 @@ package me.bobert.netneutrality.context;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* 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.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.utils.Settings;
|
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.events.message.MessageReceivedEvent;
|
||||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
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.components.LayoutComponent;
|
||||||
import net.dv8tion.jda.api.interactions.modals.Modal;
|
import net.dv8tion.jda.api.interactions.modals.Modal;
|
||||||
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Set;
|
||||||
|
import java.util.StringJoiner;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -35,35 +43,9 @@ public class MessageCommandContext extends CommandContext {
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getArgument(int index) {
|
@Override
|
||||||
return getArgs().get(index);
|
public ChannelType getType() {
|
||||||
}
|
return event.getChannelType();
|
||||||
|
|
||||||
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 + ")( )?", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message getMessage() {
|
public Message getMessage() {
|
||||||
@@ -102,11 +84,6 @@ public class MessageCommandContext extends CommandContext {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replyEphemeral(MessageCreateData messageCreateData) {
|
|
||||||
sendMessageInPrivate(messageCreateData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ack(boolean ephemeral) {
|
public void ack(boolean ephemeral) {
|
||||||
|
|
||||||
@@ -114,19 +91,206 @@ public class MessageCommandContext extends CommandContext {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteMessage() {
|
public void deleteMessage() {
|
||||||
if (message != null) {
|
if (message != null && getType() != ChannelType.PRIVATE) {
|
||||||
message.delete().queueAfter(1, TimeUnit.SECONDS);
|
message.delete().queueAfter(1, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMessageFromOwner() {
|
@Override
|
||||||
return getGuildUser().isOwner();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMessageFromCreator() {
|
private String validChoices(List<Command.Choice> choices) {
|
||||||
String creatorId = Settings.getInstance().get("NETNEUTRALITY_BOT_OWNER");
|
StringJoiner joiner = new StringJoiner(", ");
|
||||||
|
for (Command.Choice choice : choices) {
|
||||||
|
joiner.add(choice.getAsString());
|
||||||
|
}
|
||||||
|
|
||||||
return creatorId.equals(getDiscordUser().getId());
|
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
|
@Override
|
||||||
@@ -145,11 +309,10 @@ public class MessageCommandContext extends CommandContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSubCommand() {
|
public String getFullCommand() {
|
||||||
if (!getArgs().isEmpty()) {
|
String rawMessage = message.getContentRaw().trim();
|
||||||
return getArgument(0);
|
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 me.bobert.netneutrality.core.context.AbstractContext;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
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.entities.channel.middleman.GuildMessageChannel;
|
||||||
import net.dv8tion.jda.api.events.Event;
|
import net.dv8tion.jda.api.events.Event;
|
||||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||||
@@ -28,6 +29,11 @@ public class MusicChannelContext extends AbstractContext {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelType getType() {
|
||||||
|
return getChannel().getType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InteractionHook getInteractionHook() {
|
public InteractionHook getInteractionHook() {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -5,11 +5,18 @@ package me.bobert.netneutrality.context;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* 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.CommandContext;
|
||||||
import me.bobert.netneutrality.core.context.InteractionContext;
|
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.events.interaction.command.SlashCommandInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||||
import net.dv8tion.jda.api.interactions.modals.Modal;
|
import net.dv8tion.jda.api.interactions.modals.Modal;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SlashCommandContext extends CommandContext implements InteractionContext {
|
public class SlashCommandContext extends CommandContext implements InteractionContext {
|
||||||
private final SlashCommandInteractionEvent event;
|
private final SlashCommandInteractionEvent event;
|
||||||
|
|
||||||
@@ -23,6 +30,11 @@ public class SlashCommandContext extends CommandContext implements InteractionCo
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelType getType() {
|
||||||
|
return event.getChannelType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteMessage() {
|
public void deleteMessage() {
|
||||||
// not implemented
|
// not implemented
|
||||||
@@ -33,13 +45,28 @@ public class SlashCommandContext extends CommandContext implements InteractionCo
|
|||||||
event.replyModal(modal).queue();
|
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
|
@Override
|
||||||
public String parseCommandName() {
|
public String parseCommandName() {
|
||||||
return event.getName();
|
return event.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSubCommand() {
|
public String getFullCommand() {
|
||||||
return event.getFullCommandName().split(" ")[1];
|
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.InteractionContext;
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||||
|
|
||||||
public class ButtonTaskContext extends TaskContext implements InteractionContext {
|
public class ButtonTaskContext extends TaskContext implements InteractionContext {
|
||||||
@@ -22,6 +23,11 @@ public class ButtonTaskContext extends TaskContext implements InteractionContext
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelType getType() {
|
||||||
|
return event.getChannelType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return event.getComponentId();
|
return event.getComponentId();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.context.tasks;
|
|||||||
|
|
||||||
import me.bobert.netneutrality.context.AsyncContext;
|
import me.bobert.netneutrality.context.AsyncContext;
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
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.events.message.react.MessageReactionAddEvent;
|
||||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||||
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
|
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
|
||||||
@@ -30,6 +31,11 @@ public class EmojiTaskContext extends TaskContext {
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelType getType() {
|
||||||
|
return event.getChannelType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return String.format("%s:%s", getGuild().getId(), event.getMessageId());
|
return String.format("%s:%s", getGuild().getId(), event.getMessageId());
|
||||||
@@ -64,6 +70,10 @@ public class EmojiTaskContext extends TaskContext {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void replyEphemeral(MessageCreateData messageCreateData) {
|
public void replyEphemeral(MessageCreateData messageCreateData) {
|
||||||
|
if (getType() == ChannelType.PRIVATE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sendMessageInPrivate(messageCreateData);
|
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.InteractionContext;
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
||||||
|
|
||||||
public class ModalTaskContext extends TaskContext implements InteractionContext {
|
public class ModalTaskContext extends TaskContext implements InteractionContext {
|
||||||
@@ -23,6 +24,11 @@ public class ModalTaskContext extends TaskContext implements InteractionContext
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelType getType() {
|
||||||
|
return event.getChannelType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return event.getModalId();
|
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.command.Command;
|
||||||
import me.bobert.netneutrality.core.LogHandler;
|
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
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.interactions.commands.build.SlashCommandData;
|
||||||
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
|
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.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -27,25 +23,26 @@ import java.util.Set;
|
|||||||
public class CommandManager {
|
public class CommandManager {
|
||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger(CommandManager.class);
|
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) {
|
public static void init(JDA jda) {
|
||||||
logger.info("Loading commands..");
|
logger.info("Loading commands..");
|
||||||
|
|
||||||
initCommands();
|
initCommands();
|
||||||
registerSlashCommands(jda);
|
|
||||||
|
|
||||||
logger.info("Loaded {} commands!", commands.size());
|
logger.info("Loaded {} commands!", commands.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Command getCommand(String commandString) {
|
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() {
|
public static void initCommands() {
|
||||||
Reflections reflections = new Reflections("me.bobert.netneutrality.command");
|
Set<Class<? extends Command>> classes = new Reflections("me.bobert.netneutrality.command").getSubTypesOf(Command.class);
|
||||||
Set<Class<? extends Command>> classes = reflections.getSubTypesOf(Command.class);
|
|
||||||
|
|
||||||
for (Class<? extends Command> s : classes) {
|
for (Class<? extends Command> s : classes) {
|
||||||
try {
|
try {
|
||||||
if (Modifier.isAbstract(s.getModifiers())) {
|
if (Modifier.isAbstract(s.getModifiers())) {
|
||||||
@@ -53,40 +50,45 @@ public class CommandManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Command command = s.getConstructor().newInstance();
|
Command command = s.getConstructor().newInstance();
|
||||||
|
if (!command.isEnabled()) {
|
||||||
if (!command.isEnabled())
|
|
||||||
continue;
|
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())) {
|
if (!commands.containsKey(command.getCommandName())) {
|
||||||
commands.put(command.getCommandName(), command);
|
commands.put(command.getCommandName(), container);
|
||||||
}
|
}
|
||||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
} catch (Exception e) {
|
||||||
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
logger.error("Failed to instantiate command {}: {}", s.getSimpleName(), e.getMessage());
|
||||||
LogHandler.log(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerSlashCommands(JDA jda) {
|
public static void registerSlashCommands(JDA jda) {
|
||||||
CommandListUpdateAction commandListUpdateAction = jda.updateCommands();
|
CommandListUpdateAction commandListUpdateAction = jda.updateCommands();
|
||||||
List<CommandData> slashCommands = new ArrayList<>();
|
List<CommandData> slashCommands = new ArrayList<>();
|
||||||
|
|
||||||
for (Command command : commands.values()) {
|
for (CommandContainer container : commands.values()) {
|
||||||
|
Command command = container.getCommand();
|
||||||
if (!command.isEnabled() || !command.isSlashCommand()) {
|
if (!command.isEnabled() || !command.isSlashCommand()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Registering slash command: {}", command.getCommandName());
|
logger.debug("Registering slash command: {}", command.getCommandName());
|
||||||
String description = command.getDescription();
|
|
||||||
if (StringUtils.isBlank(description)) {
|
|
||||||
description = "No description provided for this command";
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SlashCommandData data = Commands.slash(command.getCommandName(), description);
|
SlashCommandData data = container.getCommandOptions().getSlashCommandData();
|
||||||
data.setDefaultPermissions(command.getSlashCommandPermission());
|
data.setDefaultPermissions(command.getSlashCommandPermission());
|
||||||
data.setGuildOnly(command.isGuildOnly());
|
data.setGuildOnly(command.isGuildOnly());
|
||||||
command.registerSlashCommandOptions(data);
|
|
||||||
|
|
||||||
slashCommands.add(data);
|
slashCommands.add(data);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -7,15 +7,26 @@ package me.bobert.netneutrality.core.command;
|
|||||||
|
|
||||||
import io.sentry.Sentry;
|
import io.sentry.Sentry;
|
||||||
import me.bobert.netneutrality.command.Command;
|
import me.bobert.netneutrality.command.Command;
|
||||||
|
import me.bobert.netneutrality.command.CommandOptions;
|
||||||
import me.bobert.netneutrality.context.MessageCommandContext;
|
import me.bobert.netneutrality.context.MessageCommandContext;
|
||||||
import me.bobert.netneutrality.context.SlashCommandContext;
|
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||||
import me.bobert.netneutrality.core.LogHandler;
|
import me.bobert.netneutrality.core.LogHandler;
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.exceptions.CommandExecutionException;
|
import me.bobert.netneutrality.exceptions.CommandExecutionException;
|
||||||
import me.bobert.netneutrality.utils.UserFunction;
|
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.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
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.ERROR;
|
||||||
import static me.bobert.netneutrality.core.command.CommandExecutionResult.Result.NOACTION;
|
import static me.bobert.netneutrality.core.command.CommandExecutionResult.Result.NOACTION;
|
||||||
|
|
||||||
@@ -33,14 +44,16 @@ public class CommandProcessor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Command command = CommandManager.getCommand(context.parseCommandName());
|
CommandContainer container = CommandManager.getCommandContainer(context.parseCommandName());
|
||||||
context.setCommand(command);
|
Command command = container.getCommand();
|
||||||
|
|
||||||
if (command == null) {
|
if (command == null) {
|
||||||
throw new IllegalArgumentException("Context has no command");
|
throw new IllegalArgumentException("Context has no command");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.setCommand(command);
|
||||||
if (command.isGuildOnly() && !context.isFromGuild()) {
|
if (command.isGuildOnly() && !context.isFromGuild()) {
|
||||||
|
context.replyEphemeral("This command is only available in a guild");
|
||||||
|
context.deleteMessage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,53 +62,149 @@ public class CommandProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
logger.info("Executing command {} on guild {}", command.getCommandName(), context.getGuild() == null ? "PrivateMessage": context.getGuild().getId());
|
logger.info("Executing command {} on guild {}", command.getCommandName(), context.getGuild() == null ? "PrivateMessage" : context.getGuild().getId());
|
||||||
configureSentry(command);
|
configureSentry(command);
|
||||||
|
|
||||||
if (context instanceof MessageCommandContext && command.needAdmin() && !UserFunction.isAdmin(context.getGuildUser())) {
|
if (!canExecute(command)) {
|
||||||
context.reply("You are not powerful enough, scrub");
|
context.reply("You are not powerful enough, scrub");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.canBeExecutedBy(context.getGuildUser())) {
|
if (!checkUsage(container.getCommandOptions())) {
|
||||||
if (command.canBeExecutedFrom(context.getChannel())) {
|
return;
|
||||||
CommandExecutionResult commandExecutionResult = null;
|
|
||||||
|
|
||||||
if (context instanceof SlashCommandContext slashCommandContext) {
|
|
||||||
commandExecutionResult = command.execute(slashCommandContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context instanceof MessageCommandContext messageCommandContext) {
|
|
||||||
commandExecutionResult = command.execute(messageCommandContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandExecutionResult == null) {
|
|
||||||
throw new RuntimeException("CommandExecutionResult is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandExecutionResult.Result result = commandExecutionResult.getResult();
|
|
||||||
String message = commandExecutionResult.getMessage();
|
|
||||||
if (result == NOACTION) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == ERROR) {
|
|
||||||
Exception exception = commandExecutionResult.getException();
|
|
||||||
logger.error("Error from command {}: {}", command.getCommandName(), message, exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.reply(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: make better
|
if (!context.isValid()) {
|
||||||
} catch (CommandExecutionException exception) {
|
StringBuilder reply = new StringBuilder("Invalid arguments provided for this command:\n");
|
||||||
LogHandler.log(exception);
|
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();
|
||||||
|
if (result == NOACTION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String message = commandExecutionResult.getMessage();
|
||||||
|
if (result == ERROR) {
|
||||||
|
logger.error("Error from command {}: {}", command.getCommandName(), message, commandExecutionResult.getException());
|
||||||
|
}
|
||||||
|
|
||||||
|
context.reply(message);
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
|
if (exception instanceof CommandExecutionException) {
|
||||||
|
LogHandler.log(exception);
|
||||||
|
}
|
||||||
|
|
||||||
LogHandler.log(new CommandExecutionException("Error during command execution", context, 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) {
|
private void configureSentry(Command command) {
|
||||||
Sentry.configureScope(scope -> {
|
Sentry.configureScope(scope -> {
|
||||||
scope.setTag("command", command.getCommandName());
|
scope.setTag("command", command.getCommandName());
|
||||||
|
|||||||
@@ -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.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.JDA;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
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 {
|
public abstract class CommandContext extends AbstractContext {
|
||||||
private Command command;
|
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) {
|
public CommandContext(JDA jda, Guild guild, MessageChannel channel, Member member, User user) {
|
||||||
super(jda, guild, channel, member, user);
|
super(jda, guild, channel, member, user);
|
||||||
|
this.options = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command getCommand() {
|
public Command getCommand() {
|
||||||
@@ -27,8 +42,97 @@ public abstract class CommandContext extends AbstractContext {
|
|||||||
this.command = command;
|
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 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.context.AsyncContext;
|
||||||
import me.bobert.netneutrality.core.GuildManager;
|
import me.bobert.netneutrality.core.GuildManager;
|
||||||
|
import me.bobert.netneutrality.utils.ContextUtils;
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.*;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
|
||||||
import net.dv8tion.jda.api.entities.User;
|
|
||||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||||
import net.dv8tion.jda.api.events.Event;
|
import net.dv8tion.jda.api.events.Event;
|
||||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||||
@@ -26,6 +25,8 @@ import java.util.function.Consumer;
|
|||||||
public interface Context {
|
public interface Context {
|
||||||
Event getEvent();
|
Event getEvent();
|
||||||
|
|
||||||
|
ChannelType getType();
|
||||||
|
|
||||||
JDA getJDA();
|
JDA getJDA();
|
||||||
|
|
||||||
InteractionHook getInteractionHook();
|
InteractionHook getInteractionHook();
|
||||||
@@ -73,7 +74,7 @@ public interface Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default void reply(String message) {
|
default void reply(String message) {
|
||||||
reply(MessageCreateData.fromContent(message));
|
replyWithLimit(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void reply(MessageEmbed embed) {
|
default void reply(MessageEmbed embed) {
|
||||||
@@ -85,7 +86,7 @@ public interface Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default void reply(String format, Object... arguments) {
|
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) {
|
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) {
|
default void sendMessageInPrivate(String message) {
|
||||||
sendMessageInPrivate(message, List.of());
|
sendMessageInPrivateWithLimit(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendMessageInPrivate(String message, List<LayoutComponent> components) {
|
default void sendMessageInPrivate(String message, List<LayoutComponent> components) {
|
||||||
@@ -179,4 +180,16 @@ public interface Context {
|
|||||||
default void sendMessageInPrivate(List<MessageEmbed> embeds) {
|
default void sendMessageInPrivate(List<MessageEmbed> embeds) {
|
||||||
sendMessageInPrivate(MessageCreateData.fromEmbeds(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
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a task that has a known ID and is loaded at runtime.
|
* Represents a task that has a known ID and is loaded at runtime.
|
||||||
* This can be any task and is not necessarily a button.
|
* This can be any task and is not necessarily a button.
|
||||||
*/
|
*/
|
||||||
public interface BuiltInTask extends Task {
|
public interface BuiltInTask extends Task {
|
||||||
|
|
||||||
static TaskButtonCreator createButton(Class<? extends BuiltInTask> clazz) {
|
static TaskButtonCreator createButton(Class<? extends BuiltInTask> clazz) {
|
||||||
try {
|
BuiltInTask builtInTask = TaskManager.getInstance().getTaskMap().values().stream().filter(clazz::isInstance).map(task -> (BuiltInTask) task).findFirst().orElse(null);
|
||||||
BuiltInTask task = clazz.getConstructor().newInstance();
|
if (builtInTask == null) {
|
||||||
return new TaskButtonCreator(task.getId());
|
throw new IllegalArgumentException("Task class " + clazz.getName() + " was not registered by the task manager.");
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new TaskButtonCreator(builtInTask.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
package me.bobert.netneutrality.exceptions;
|
package me.bobert.netneutrality.exceptions;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
*
|
*
|
||||||
@@ -8,9 +7,6 @@ package me.bobert.netneutrality.exceptions;
|
|||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs the error internally, without sending a message
|
|
||||||
*/
|
|
||||||
public class CommandExecutionException extends ContextException {
|
public class CommandExecutionException extends ContextException {
|
||||||
|
|
||||||
public CommandExecutionException(String message, CommandContext context, Throwable cause) {
|
public CommandExecutionException(String message, CommandContext context, Throwable cause) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class BotInfo extends AbstractBuiltInTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(TaskContext context) {
|
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");
|
"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.context.TaskContext;
|
||||||
import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask;
|
import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask;
|
||||||
import me.bobert.netneutrality.utils.MessageFunction;
|
import me.bobert.netneutrality.utils.MessageFunction;
|
||||||
|
import me.bobert.netneutrality.utils.Settings;
|
||||||
|
|
||||||
public class CommandHelp extends AbstractBuiltInTask {
|
public class CommandHelp extends AbstractBuiltInTask {
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ public class CommandHelp extends AbstractBuiltInTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(TaskContext context) {
|
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
|
@Override
|
||||||
public void execute(TaskContext context) {
|
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");
|
"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 {
|
private void processManager(MusicManager manager) throws InterruptedException {
|
||||||
logger.debug("Processing MusicPlayerAutoDisconnectThread for guild {}", manager.getGuild().getId());
|
|
||||||
AudioChannel channel = manager.getGuild().getAudioManager().getConnectedChannel();
|
AudioChannel channel = manager.getGuild().getAudioManager().getConnectedChannel();
|
||||||
|
|
||||||
if (channel != null) {
|
if (channel != null) {
|
||||||
|
logger.debug("Processing MusicPlayerAutoDisconnectThread for guild {}", manager.getGuild().getId());
|
||||||
if (conditionsMetToDisconnect(manager)) {
|
if (conditionsMetToDisconnect(manager)) {
|
||||||
logger.debug("Guild {}: Sleeping 30 seconds and checking again", manager.getGuild().getId());
|
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)
|
// 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 io.sentry.Sentry;
|
||||||
import me.bobert.netneutrality.command.Command;
|
import me.bobert.netneutrality.command.Command;
|
||||||
import me.bobert.netneutrality.command.CommandType;
|
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.command.CommandManager;
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.core.context.Context;
|
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.Member;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
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.commons.lang3.time.DurationFormatUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -203,7 +203,8 @@ public class MessageFunction {
|
|||||||
public static String buildHelpMessage() {
|
public static String buildHelpMessage() {
|
||||||
Map<CommandType, String> help = new HashMap<>();
|
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) {
|
if (command.getType() == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -233,19 +234,19 @@ public class MessageFunction {
|
|||||||
|
|
||||||
String subtext = "\n\n" +
|
String subtext = "\n\n" +
|
||||||
"-# The bot supports both types of commands: slash (/) and message ($), " +
|
"-# 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> ";
|
"-# To get help for a specific command, please use /help <command> ";
|
||||||
|
|
||||||
return String.join("\n", help.values()) + subtext;
|
return String.join("\n", help.values()) + subtext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String buildCommandHelpMessage(Command command) {
|
public static String buildCommandHelpMessage(CommandContainer container) {
|
||||||
String message = "## Command info for /" + command.getCommandName();
|
|
||||||
if (command.getDescription() != null) {
|
|
||||||
message += "\n- Description: " + command.getDescription();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return message;
|
||||||
}
|
}
|
||||||
@@ -280,7 +281,7 @@ public class MessageFunction {
|
|||||||
if (exception.getCause() != null) {
|
if (exception.getCause() != null) {
|
||||||
String cause;
|
String cause;
|
||||||
if (exception.getCause().getMessage() != null && !exception.getCause().getMessage().isEmpty()) {
|
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 {
|
} else {
|
||||||
cause = exception.getCause().getClass().getName();
|
cause = exception.getCause().getClass().getName();
|
||||||
}
|
}
|
||||||
@@ -316,19 +317,4 @@ public class MessageFunction {
|
|||||||
return editEmbed.build();
|
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.MusicChannelContext;
|
||||||
|
import me.bobert.netneutrality.context.SlashCommandContext;
|
||||||
import me.bobert.netneutrality.core.context.Context;
|
import me.bobert.netneutrality.core.context.Context;
|
||||||
import me.bobert.netneutrality.exceptions.ContextException;
|
import me.bobert.netneutrality.exceptions.ContextException;
|
||||||
import me.bobert.netneutrality.music.MusicManager;
|
import me.bobert.netneutrality.music.MusicManager;
|
||||||
@@ -87,6 +88,14 @@ public class MusicUtils {
|
|||||||
return memberVoiceState.getChannel();
|
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) {
|
public static boolean isUserDj(Member member) {
|
||||||
MusicManager manager = MusicManager.get(member.getGuild());
|
MusicManager manager = MusicManager.get(member.getGuild());
|
||||||
Member dj = manager.getScheduler().getDj();
|
Member dj = manager.getScheduler().getDj();
|
||||||
|
|||||||
@@ -6,12 +6,22 @@ package me.bobert.netneutrality.utils;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* 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.Permission;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
|
|
||||||
public class UserFunction {
|
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) {
|
public static boolean isAdmin(Member user) {
|
||||||
boolean isAdmin = false;
|
boolean isAdmin = false;
|
||||||
for(Role role : user.getRoles()) {
|
for(Role role : user.getRoles()) {
|
||||||
|
|||||||
Reference in new issue
Block a user