2024-06-24 12:56:01 +00:00
|
|
|
package cc.fascinated.bat.service;
|
|
|
|
|
|
|
|
import cc.fascinated.bat.command.BatCommand;
|
2024-06-25 23:31:16 +00:00
|
|
|
import cc.fascinated.bat.command.BatCommandExecutor;
|
2024-06-24 12:56:01 +00:00
|
|
|
import cc.fascinated.bat.command.BatSubCommand;
|
|
|
|
import cc.fascinated.bat.common.EmbedUtils;
|
2024-06-25 10:55:26 +00:00
|
|
|
import cc.fascinated.bat.model.BatGuild;
|
|
|
|
import cc.fascinated.bat.model.BatUser;
|
2024-06-24 12:56:01 +00:00
|
|
|
import lombok.NonNull;
|
|
|
|
import lombok.extern.log4j.Log4j2;
|
|
|
|
import net.dv8tion.jda.api.JDA;
|
2024-06-25 23:31:16 +00:00
|
|
|
import net.dv8tion.jda.api.Permission;
|
2024-06-24 12:56:01 +00:00
|
|
|
import net.dv8tion.jda.api.entities.Guild;
|
|
|
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
|
|
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
import org.springframework.context.annotation.DependsOn;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
2024-06-25 23:31:16 +00:00
|
|
|
import java.util.ArrayList;
|
2024-06-24 12:56:01 +00:00
|
|
|
import java.util.HashMap;
|
2024-06-25 23:31:16 +00:00
|
|
|
import java.util.List;
|
2024-06-24 12:56:01 +00:00
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @author Fascinated (fascinated7)
|
|
|
|
*/
|
2024-06-26 15:17:57 +00:00
|
|
|
@Service
|
|
|
|
@Log4j2
|
2024-06-24 12:56:01 +00:00
|
|
|
@DependsOn("discordService")
|
|
|
|
public class CommandService extends ListenerAdapter {
|
|
|
|
/**
|
|
|
|
* The registered commands
|
|
|
|
*/
|
|
|
|
private final Map<String, BatCommand> commands = new HashMap<>();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The guild service to use
|
|
|
|
*/
|
|
|
|
private final GuildService guildService;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The user service to use
|
|
|
|
*/
|
|
|
|
private final UserService userService;
|
|
|
|
|
|
|
|
@Autowired
|
2024-06-25 16:20:19 +00:00
|
|
|
public CommandService(@NonNull GuildService guildService, @NonNull UserService userService) {
|
2024-06-24 12:56:01 +00:00
|
|
|
this.guildService = guildService;
|
|
|
|
this.userService = userService;
|
|
|
|
DiscordService.JDA.addEventListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers a command
|
|
|
|
*
|
|
|
|
* @param command The command to register
|
|
|
|
*/
|
|
|
|
public void registerCommand(@NonNull BatCommand command) {
|
2024-06-25 14:43:36 +00:00
|
|
|
if (commands.get(command.getName().toLowerCase()) != null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
log.info("Registered command \"{}\"", command.getName());
|
2024-06-24 12:56:01 +00:00
|
|
|
commands.put(command.getName().toLowerCase(), command);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers all slash commands
|
|
|
|
*/
|
|
|
|
public void registerSlashCommands() {
|
|
|
|
log.info("Registering all slash commands");
|
|
|
|
JDA jda = DiscordService.JDA;
|
|
|
|
long before = System.currentTimeMillis();
|
|
|
|
|
|
|
|
// Unregister all commands that Discord has but we don't
|
|
|
|
jda.retrieveCommands().complete().forEach(command -> {
|
|
|
|
if (commands.containsKey(command.getName())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
jda.deleteCommandById(command.getId()).complete(); // Unregister the command on Discord
|
|
|
|
log.info("Unregistered unknown command \"{}\" from Discord", command.getName());
|
|
|
|
});
|
|
|
|
|
|
|
|
// Register all commands
|
2024-06-24 14:45:53 +00:00
|
|
|
jda.updateCommands().addCommands(commands.values().stream().map(BatCommand::getCommandData).toList()).complete();
|
2024-06-24 12:56:01 +00:00
|
|
|
log.info("Registered all slash commands in {}ms", System.currentTimeMillis() - before);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
|
|
|
|
Guild discordGuild = event.getGuild();
|
2024-06-25 23:41:47 +00:00
|
|
|
if (event.getUser().isBot()) {
|
2024-06-24 12:56:01 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
String commandName = event.getName();
|
|
|
|
BatCommand command = commands.get(commandName);
|
|
|
|
if (command == null) {
|
|
|
|
return;
|
|
|
|
}
|
2024-06-26 19:41:31 +00:00
|
|
|
boolean ranInsideGuild = discordGuild != null;
|
|
|
|
BatGuild guild = ranInsideGuild ? guildService.getGuild(discordGuild.getId()) : null;
|
2024-06-24 12:56:01 +00:00
|
|
|
BatUser user = userService.getUser(event.getUser().getId());
|
2024-06-25 23:31:16 +00:00
|
|
|
|
2024-06-24 12:56:01 +00:00
|
|
|
try {
|
2024-06-25 23:31:16 +00:00
|
|
|
BatCommandExecutor executor = null;
|
|
|
|
List<Permission> requiredPermissions = new ArrayList<>();
|
|
|
|
|
2024-06-25 10:14:12 +00:00
|
|
|
// No args provided, use the main command executor
|
2024-06-24 16:42:57 +00:00
|
|
|
if (event.getInteraction().getSubcommandName() == null) {
|
2024-06-25 23:31:16 +00:00
|
|
|
executor = command;
|
|
|
|
requiredPermissions.addAll(command.getRequiredPermissions());
|
|
|
|
} else {
|
|
|
|
// Subcommand provided, use the subcommand executor
|
|
|
|
for (Map.Entry<String, BatSubCommand> subCommand : command.getSubCommands().entrySet()) {
|
|
|
|
if (subCommand.getKey().equalsIgnoreCase(event.getInteraction().getSubcommandName())) {
|
|
|
|
executor = subCommand.getValue();
|
|
|
|
requiredPermissions.addAll(subCommand.getValue().getRequiredPermissions());
|
|
|
|
requiredPermissions.addAll(command.getRequiredPermissions()); // not sure if we'd want this, but it's here for now
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (executor == null) {
|
|
|
|
event.replyEmbeds(EmbedUtils.errorEmbed()
|
|
|
|
.setDescription("Unable to find a command executor the command name ):")
|
|
|
|
.build()).queue();
|
2024-06-25 10:14:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-06-25 23:31:16 +00:00
|
|
|
// Check if the user has the required permissions
|
2024-06-26 19:41:31 +00:00
|
|
|
if (ranInsideGuild && event.getMember() != null) {
|
2024-06-25 23:31:16 +00:00
|
|
|
List<Permission> missingPermissions = new ArrayList<>();
|
|
|
|
for (Permission permission : requiredPermissions) {
|
|
|
|
if (!event.getMember().hasPermission(permission)) {
|
|
|
|
missingPermissions.add(permission);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!missingPermissions.isEmpty()) {
|
|
|
|
event.replyEmbeds(EmbedUtils.errorEmbed()
|
2024-06-26 15:17:57 +00:00
|
|
|
.setDescription("You are missing the following permissions to execute this command: " + missingPermissions)
|
|
|
|
.build())
|
|
|
|
.setEphemeral(true)
|
|
|
|
.queue();
|
2024-06-25 23:31:16 +00:00
|
|
|
return;
|
2024-06-24 12:56:01 +00:00
|
|
|
}
|
|
|
|
}
|
2024-06-27 12:36:03 +00:00
|
|
|
log.info("Executing command \"{}\" for user \"{}\"", commandName, user.getDiscordUser().getName());
|
2024-06-26 19:41:31 +00:00
|
|
|
executor.execute(guild, user, ranInsideGuild ? event.getChannel().asTextChannel() : event.getChannel().asPrivateChannel(),
|
2024-06-25 23:41:47 +00:00
|
|
|
event.getMember(), event.getInteraction());
|
2024-06-24 12:56:01 +00:00
|
|
|
} catch (Exception ex) {
|
|
|
|
log.error("An error occurred while executing command \"{}\"", commandName, ex);
|
2024-06-25 12:55:54 +00:00
|
|
|
|
2024-06-25 12:59:02 +00:00
|
|
|
event.replyEmbeds(EmbedUtils.successEmbed()
|
2024-06-26 15:17:57 +00:00
|
|
|
.setDescription("An error occurred while executing the command\n\n" + ex.getLocalizedMessage())
|
|
|
|
.build())
|
|
|
|
.queue();
|
2024-06-24 12:56:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|