2024-06-24 12:56:01 +00:00
|
|
|
package cc.fascinated.bat.service;
|
|
|
|
|
|
|
|
import cc.fascinated.bat.command.BatCommand;
|
|
|
|
import cc.fascinated.bat.command.BatSubCommand;
|
|
|
|
import cc.fascinated.bat.command.impl.global.beatsaber.scoresaber.LinkSubCommand;
|
|
|
|
import cc.fascinated.bat.command.impl.global.beatsaber.scoresaber.ScoreSaberCommand;
|
|
|
|
import cc.fascinated.bat.command.impl.global.beatsaber.scoresaber.UserSubCommand;
|
|
|
|
import cc.fascinated.bat.common.EmbedUtils;
|
|
|
|
import cc.fascinated.bat.model.BatGuild;
|
|
|
|
import cc.fascinated.bat.model.user.BatUser;
|
|
|
|
import lombok.NonNull;
|
|
|
|
import lombok.extern.log4j.Log4j2;
|
|
|
|
import net.dv8tion.jda.api.JDA;
|
|
|
|
import net.dv8tion.jda.api.entities.Guild;
|
|
|
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
|
|
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
|
|
|
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
|
import org.springframework.context.annotation.DependsOn;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @author Fascinated (fascinated7)
|
|
|
|
*/
|
|
|
|
@Service @Log4j2
|
|
|
|
@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;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The application context to use
|
|
|
|
*/
|
|
|
|
private final ApplicationContext context;
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
public CommandService(@NonNull GuildService guildService, @NonNull UserService userService, @NonNull ApplicationContext context) {
|
|
|
|
this.guildService = guildService;
|
|
|
|
this.userService = userService;
|
|
|
|
this.context = context;
|
|
|
|
DiscordService.JDA.addEventListener(this);
|
|
|
|
|
|
|
|
// Guild commands
|
|
|
|
// todo: add some, duh
|
|
|
|
|
|
|
|
// Global commands
|
|
|
|
registerCommand(context.getBean(ScoreSaberCommand.class)
|
|
|
|
.addSubCommand("link", context.getBean(LinkSubCommand.class))
|
|
|
|
.addSubCommand("user", context.getBean(UserSubCommand.class)
|
|
|
|
));
|
|
|
|
|
|
|
|
registerSlashCommands(); // Register all slash commands
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers a command
|
|
|
|
*
|
|
|
|
* @param command The command to register
|
|
|
|
*/
|
|
|
|
public void registerCommand(@NonNull BatCommand command) {
|
|
|
|
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();
|
|
|
|
if (discordGuild == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (event.getUser().isBot()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (event.getMember() == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
String commandName = event.getName();
|
|
|
|
BatCommand command = commands.get(commandName);
|
|
|
|
if (command == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BatGuild guild = guildService.getGuild(discordGuild.getId());
|
|
|
|
BatUser user = userService.getUser(event.getUser().getId());
|
|
|
|
|
|
|
|
// No args provided, use the main command executor
|
|
|
|
List<OptionMapping> options = event.getInteraction().getOptions();
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (options.isEmpty()) {
|
|
|
|
command.execute(guild, user, event.getChannel().asTextChannel(), event.getMember(), event.getInteraction(), null);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the sub command exists
|
|
|
|
for (Map.Entry<String, BatSubCommand> subCommand : command.getSubCommands().entrySet()) {
|
|
|
|
for (OptionMapping option : options) {
|
|
|
|
if (subCommand.getKey().equalsIgnoreCase(option.getName())) {
|
|
|
|
subCommand.getValue().execute(guild, user, event.getChannel().asTextChannel(), event.getMember(), event.getInteraction(), option);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception ex) {
|
|
|
|
log.error("An error occurred while executing command \"{}\"", commandName, ex);
|
|
|
|
event.replyEmbeds(EmbedUtils.buildErrorEmbed("An error occurred while executing the command\n\n" +
|
|
|
|
ex.getLocalizedMessage()).build()).queue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|