package fr.lucasdupont.service import fr.lucasdupont.configuration.JdaConfiguration import fr.lucasdupont.gaytabot.command.Command import fr.lucasdupont.gaytabot.command.toCommandData import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.JDABuilder import net.dv8tion.jda.api.entities.Activity import net.dv8tion.jda.api.events.GenericEvent import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent import net.dv8tion.jda.api.hooks.ListenerAdapter import net.dv8tion.jda.api.requests.GatewayIntent import net.dv8tion.jda.api.utils.cache.CacheFlag import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationEventPublisher import org.springframework.context.PayloadApplicationEvent import org.springframework.context.event.EventListener import org.springframework.stereotype.Service @Service @EnableConfigurationProperties(JdaConfiguration::class) class JdaService( applicationContext: ApplicationContext, jdaConfiguration: JdaConfiguration, publisher: ApplicationEventPublisher ) { private final val jda: JDA private final val commands: Map init { val requiredIntents: Set = jdaConfiguration.cacheFlags .mapNotNull(CacheFlag::getRequiredIntent) .toSet() val builder = JDABuilder.createDefault(jdaConfiguration.token) .setStatus(jdaConfiguration.onlineStatus) .enableCache(jdaConfiguration.cacheFlags) .enableIntents(requiredIntents) if (jdaConfiguration.activity != null) { builder.setActivity(Activity.playing(jdaConfiguration.activity!!)) } jda = builder .build() .awaitReady() .also { jda -> jda.addEventListener(object : ListenerAdapter() { override fun onGenericEvent(event: GenericEvent) { publisher.publishEvent(PayloadApplicationEvent(jda, event)) } }) } val contextCommands = applicationContext.getBeansOfType(Command::class.java).values commands = contextCommands.associateBy { it.name } val commandDataList = contextCommands.map { it.toCommandData() } jda.updateCommands() .addCommands(commandDataList) .queue() } @EventListener(SlashCommandInteractionEvent::class) fun onSlashCommand(event: SlashCommandInteractionEvent) { commands[event.name]?.let { command -> runCatching { command.execute(event) } .onFailure { e -> error("Error while executing command '${event.name}', $e") } } } }