From 3bb0182ce29fd18ff0176b4fb1945a22b9a6b737 Mon Sep 17 00:00:00 2001 From: dkim19375 Date: Sat, 22 May 2021 10:16:16 -0400 Subject: [PATCH] fixed bug, added CustomJDABuilder --- build.gradle | 2 +- .../me/dkim19375/dkim19375jdautils/BotBase.kt | 97 ++++- .../dkim19375jdautils/command/CommandType.kt | 2 +- .../dkim19375jdautils/command/HelpCommand.kt | 3 +- .../impl/CustomJDABuilder.kt | 335 ++++++++++++++++++ 5 files changed, 420 insertions(+), 19 deletions(-) create mode 100644 src/main/kotlin/me/dkim19375/dkim19375jdautils/impl/CustomJDABuilder.kt diff --git a/build.gradle b/build.gradle index a0332e1..79b3495 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 compileJava.options.encoding 'UTF-8' group 'me.dkim19375' -version '2.3.0' +version '2.4.0' //noinspection GrUnresolvedAccess compileKotlin.kotlinOptions { diff --git a/src/main/kotlin/me/dkim19375/dkim19375jdautils/BotBase.kt b/src/main/kotlin/me/dkim19375/dkim19375jdautils/BotBase.kt index 1a2e8f3..a29ff68 100644 --- a/src/main/kotlin/me/dkim19375/dkim19375jdautils/BotBase.kt +++ b/src/main/kotlin/me/dkim19375/dkim19375jdautils/BotBase.kt @@ -3,13 +3,14 @@ package me.dkim19375.dkim19375jdautils import dev.minn.jda.ktx.injectKTX import me.dkim19375.dkim19375jdautils.annotation.API import me.dkim19375.dkim19375jdautils.command.Command +import me.dkim19375.dkim19375jdautils.command.CommandType import me.dkim19375.dkim19375jdautils.command.HelpCommand import me.dkim19375.dkim19375jdautils.command.OTHER_TYPE import me.dkim19375.dkim19375jdautils.event.CustomListener import me.dkim19375.dkim19375jdautils.event.EventListener +import me.dkim19375.dkim19375jdautils.impl.CustomJDABuilder import me.dkim19375.dkim19375jdautils.managers.SpecialEventsManager import net.dv8tion.jda.api.JDA -import net.dv8tion.jda.api.JDABuilder import net.dv8tion.jda.api.requests.GatewayIntent import java.util.* import kotlin.concurrent.thread @@ -23,21 +24,83 @@ import kotlin.system.exitProcess @API @Suppress("LeakingThis") abstract class BotBase { + /** + * The name of the bot + */ abstract val name: String + + /** + * The token of the bot + */ abstract val token: String + + /** + * Whether to Inject KTS from JDA-KTS + */ open val injectKTS = false + + /** + * The base JDA builder + */ + open val baseJDABuilder: (Unit) -> CustomJDABuilder = builder@{ + val builder = CustomJDABuilder.createDefault(token) + if (injectKTS) { + builder.actions.add { it.injectKTX() } + } + return@builder builder.enableIntents(intents) + .addEventListeners(eventsManager, EventListener(this)) + } + + /** + * Allows you to run methods on [CustomJDABuilder], overriding the ones ran by the [BotBase#onStart][BotBase.onStart] + */ + open val jdaBuilderActions: ((CustomJDABuilder) -> CustomJDABuilder)? = null + + /** + * The listener to detect if a command is valid to send + */ open val customListener: CustomListener = object : CustomListener() {} - open val intents = mutableSetOf(GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.DIRECT_MESSAGE_REACTIONS) + /** + * [GatewayIntents][GatewayIntent] that should be enabled + */ + @API + val intents = mutableSetOf(GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.DIRECT_MESSAGE_REACTIONS) + + /** + * The [JDA] instance + */ lateinit var jda: JDA - val commandTypes = mutableSetOf(OTHER_TYPE) - val commands = mutableSetOf(HelpCommand(this)) + /** + * [CommandTypes][me.dkim19375.dkim19375jdautils.command.CommandType] that should be registered + */ + open val commandTypes = mutableSetOf(OTHER_TYPE) + + /** + * [Commands][Command] that should be registered + */ + open val commands = mutableSetOf(HelpCommand(this)) + + /** + * An [Events Manager][SpecialEventsManager] useful for handling events such as reaction add listeners + */ @API - val eventsManager: SpecialEventsManager = SpecialEventsManager(this) + open val eventsManager: SpecialEventsManager = SpecialEventsManager(this) + /** + * Console commands that should be triggered. + * + * The key of the map: The base command + * + * The value of the map: The raw string/input + */ @API - val consoleCommands = mutableMapOf Unit>() + open val consoleCommands = mutableMapOf Unit>() + + /** + * True if the bot is started, false if not + */ private var started = false /** @@ -52,6 +115,17 @@ abstract class BotBase { */ abstract fun getPrefix(guild: String): String + /** + * Get all command types + * + * @return All [CommandTypes][CommandType] from [commands] + */ + open fun getAllCommandTypes(): Set { + val types = commandTypes.toMutableSet() + types.addAll(commands.map(Command::type)) + return types + } + /** * @param stopCommandEnabled True if the stop console command should be enabled, false if not */ @@ -62,15 +136,8 @@ abstract class BotBase { } started = true println("Starting bot") - val builder = JDABuilder.createDefault(token) - if (injectKTS) { - builder.injectKTX() - } - builder.enableIntents(intents) - val jda = builder.build() - this.jda = jda - jda.addEventListener(EventListener(this)) - jda.addEventListener(eventsManager) + val builder = jdaBuilderActions?.let { it(baseJDABuilder(Unit)) } ?: baseJDABuilder(Unit) + jda = builder.getBuilder().build() Runtime.getRuntime().addShutdownHook(thread(false) { if (jda.status != JDA.Status.SHUTDOWN && jda.status != JDA.Status.SHUTTING_DOWN) { println("Stopping the bot!") diff --git a/src/main/kotlin/me/dkim19375/dkim19375jdautils/command/CommandType.kt b/src/main/kotlin/me/dkim19375/dkim19375jdautils/command/CommandType.kt index ce181d7..1762f86 100644 --- a/src/main/kotlin/me/dkim19375/dkim19375jdautils/command/CommandType.kt +++ b/src/main/kotlin/me/dkim19375/dkim19375jdautils/command/CommandType.kt @@ -4,7 +4,7 @@ import me.dkim19375.dkim19375jdautils.BotBase import org.apache.commons.lang3.StringUtils fun String.getCommandType(bot: BotBase): CommandType? { - for (type in bot.commandTypes) { + for (type in bot.getAllCommandTypes()) { if (type.name.equals(this, ignoreCase = true)) { return type } diff --git a/src/main/kotlin/me/dkim19375/dkim19375jdautils/command/HelpCommand.kt b/src/main/kotlin/me/dkim19375/dkim19375jdautils/command/HelpCommand.kt index 534401a..437ea7d 100644 --- a/src/main/kotlin/me/dkim19375/dkim19375jdautils/command/HelpCommand.kt +++ b/src/main/kotlin/me/dkim19375/dkim19375jdautils/command/HelpCommand.kt @@ -6,7 +6,6 @@ import me.dkim19375.dkim19375jdautils.embed.EmbedManager import me.dkim19375.dkim19375jdautils.embed.EmbedUtils import me.dkim19375.dkim19375jdautils.util.getCommand import me.dkim19375.dkim19375jdautils.util.getOfType -import net.dv8tion.jda.api.events.message.MessageReceivedEvent import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent import java.awt.Color @@ -27,7 +26,7 @@ open class HelpCommand(private val bot: BotBase) : Command(bot) { override val aliases = setOf() override val description = "See the bot's commands" override val arguments: Set - get() = bot.commandTypes.map { type -> + get() = bot.getAllCommandTypes().map { type -> CommandArg( this, type.displayname.lowercase(), diff --git a/src/main/kotlin/me/dkim19375/dkim19375jdautils/impl/CustomJDABuilder.kt b/src/main/kotlin/me/dkim19375/dkim19375jdautils/impl/CustomJDABuilder.kt new file mode 100644 index 0000000..5270648 --- /dev/null +++ b/src/main/kotlin/me/dkim19375/dkim19375jdautils/impl/CustomJDABuilder.kt @@ -0,0 +1,335 @@ +package me.dkim19375.dkim19375jdautils.impl + +import com.neovisionaries.ws.client.WebSocketFactory +import net.dv8tion.jda.api.GatewayEncoding +import net.dv8tion.jda.api.JDABuilder +import net.dv8tion.jda.api.OnlineStatus +import net.dv8tion.jda.api.audio.factory.IAudioSendFactory +import net.dv8tion.jda.api.entities.Activity +import net.dv8tion.jda.api.hooks.IEventManager +import net.dv8tion.jda.api.hooks.VoiceDispatchInterceptor +import net.dv8tion.jda.api.requests.GatewayIntent +import net.dv8tion.jda.api.utils.ChunkingFilter +import net.dv8tion.jda.api.utils.Compression +import net.dv8tion.jda.api.utils.MemberCachePolicy +import net.dv8tion.jda.api.utils.SessionController +import net.dv8tion.jda.api.utils.cache.CacheFlag +import okhttp3.OkHttpClient +import java.util.concurrent.ConcurrentMap +import java.util.concurrent.ExecutorService +import java.util.concurrent.ScheduledExecutorService +import javax.annotation.CheckReturnValue + +@Suppress("unused", "MemberVisibilityCanBePrivate") +class CustomJDABuilder(val creation: (Unit) -> JDABuilder) { + val actions = mutableListOf<(JDABuilder) -> JDABuilder>() + + companion object { + @CheckReturnValue + fun createDefault(token: String): CustomJDABuilder = CustomJDABuilder { JDABuilder.createDefault(token) } + + @CheckReturnValue + fun createDefault( + token: String, + intent: GatewayIntent, + vararg intents: GatewayIntent + ): CustomJDABuilder = CustomJDABuilder { JDABuilder.createDefault(token, intent, *intents) } + + @CheckReturnValue + fun createDefault(token: String, intents: Collection): CustomJDABuilder = + CustomJDABuilder { JDABuilder.createDefault(token, intents) } + + @CheckReturnValue + fun createLight(token: String): CustomJDABuilder = CustomJDABuilder { JDABuilder.createLight(token) } + + @CheckReturnValue + fun createLight( + token: String, + intent: GatewayIntent, + vararg intents: GatewayIntent + ): CustomJDABuilder = CustomJDABuilder { + JDABuilder.createLight(token, intent, *intents) + } + + @CheckReturnValue + fun createLight(token: String, intents: Collection): CustomJDABuilder = + CustomJDABuilder { JDABuilder.createLight(token, intents) } + + @CheckReturnValue + fun create(intent: GatewayIntent, vararg intents: GatewayIntent): CustomJDABuilder = + CustomJDABuilder { JDABuilder.create(intent, *intents) } + + @CheckReturnValue + fun create(intents: Collection): CustomJDABuilder = + CustomJDABuilder { JDABuilder.create(intents) } + + @CheckReturnValue + fun create(token: String?, intent: GatewayIntent, vararg intents: GatewayIntent): CustomJDABuilder = + CustomJDABuilder { JDABuilder.create(token, intent, *intents) } + + @CheckReturnValue + fun create(token: String?, intents: Collection): CustomJDABuilder = + CustomJDABuilder { JDABuilder.create(token, intents) } + } + + fun setGatewayEncoding(encoding: GatewayEncoding): CustomJDABuilder { + actions.add { it.setGatewayEncoding(encoding) } + return this + } + + fun setRawEventsEnabled(enable: Boolean): CustomJDABuilder { + actions.add { it.setRawEventsEnabled(enable) } + return this + } + + fun setRelativeRateLimit(enable: Boolean): CustomJDABuilder { + actions.add { it.setRelativeRateLimit(enable) } + return this + } + + fun enableCache(flags: Collection): CustomJDABuilder { + actions.add { it.disableCache(flags) } + return this + } + + fun enableCache(flag: CacheFlag, vararg flags: CacheFlag): CustomJDABuilder { + actions.add { it.enableCache(flag, *flags) } + return this + } + + fun disableCache(flags: Collection): CustomJDABuilder { + actions.add { it.disableCache(flags) } + return this + } + + fun disableCache(flag: CacheFlag, vararg flags: CacheFlag): CustomJDABuilder { + actions.add { it.disableCache(flag, *flags) } + return this + } + + fun setMemberCachePolicy(policy: MemberCachePolicy?): CustomJDABuilder { + actions.add { it.setMemberCachePolicy(policy) } + return this + } + + fun setContextMap(map: ConcurrentMap?): CustomJDABuilder { + actions.add { it.setContextMap(map) } + return this + } + + fun setContextEnabled(enable: Boolean): CustomJDABuilder { + actions.add { it.setContextEnabled(enable) } + return this + } + + fun setCompression(compression: Compression): CustomJDABuilder { + actions.add { it.setCompression(compression) } + return this + } + + fun setRequestTimeoutRetry(retryOnTimeout: Boolean): CustomJDABuilder { + actions.add { it.setRequestTimeoutRetry(retryOnTimeout) } + return this + } + + fun setToken(token: String?): CustomJDABuilder { + actions.add { it.setToken(token) } + return this + } + + fun setHttpClientBuilder(builder: OkHttpClient.Builder?): CustomJDABuilder { + actions.add { it.setHttpClientBuilder(builder) } + return this + } + + fun setHttpClient(client: OkHttpClient?): CustomJDABuilder { + actions.add { it.setHttpClient(client) } + return this + } + + fun setWebsocketFactory(factory: WebSocketFactory?): CustomJDABuilder { + actions.add { it.setWebsocketFactory(factory) } + return this + } + + fun setRateLimitPool(pool: ScheduledExecutorService?): CustomJDABuilder { + actions.add { it.setRateLimitPool(pool) } + return this + } + + fun setRateLimitPool(pool: ScheduledExecutorService?, automaticShutdown: Boolean): CustomJDABuilder { + actions.add { it.setRateLimitPool(pool, automaticShutdown) } + return this + } + + fun setGatewayPool(pool: ScheduledExecutorService?): CustomJDABuilder { + actions.add { it.setGatewayPool(pool) } + return this + } + + fun setGatewayPool(pool: ScheduledExecutorService?, automaticShutdown: Boolean): CustomJDABuilder { + actions.add { it.setGatewayPool(pool, automaticShutdown) } + return this + } + + fun setCallbackPool(executor: ExecutorService?): CustomJDABuilder { + actions.add { it.setCallbackPool(executor) } + return this + } + + fun setCallbackPool(executor: ExecutorService, automaticShutdown: Boolean): CustomJDABuilder { + actions.add { it.setCallbackPool(executor, automaticShutdown) } + return this + } + + fun setEventPool(executor: ExecutorService?): CustomJDABuilder { + actions.add { it.setEventPool(executor) } + return this + } + + fun setEventPool(executor: ExecutorService?, automaticShutdown: Boolean): CustomJDABuilder { + actions.add { it.setEventPool(executor, automaticShutdown) } + return this + } + + fun setAudioPool(pool: ScheduledExecutorService?): CustomJDABuilder { + actions.add { it.setAudioPool(pool) } + return this + } + + fun setAudioPool(pool: ScheduledExecutorService?, automaticShutdown: Boolean): CustomJDABuilder { + actions.add { it.setAudioPool(pool, automaticShutdown) } + return this + } + + fun setBulkDeleteSplittingEnabled(enabled: Boolean): CustomJDABuilder { + actions.add { it.setBulkDeleteSplittingEnabled(enabled) } + return this + } + + fun setEnableShutdownHook(enable: Boolean): CustomJDABuilder { + actions.add { it.setEnableShutdownHook(enable) } + return this + } + + fun setAutoReconnect(autoReconnect: Boolean): CustomJDABuilder { + actions.add { it.setAutoReconnect(autoReconnect) } + return this + } + + fun setEventManager(manager: IEventManager?): CustomJDABuilder { + actions.add { it.setEventManager(manager) } + return this + } + + fun setAudioSendFactory(factory: IAudioSendFactory?): CustomJDABuilder { + actions.add { it.setAudioSendFactory(factory) } + return this + } + + fun setIdle(idle: Boolean): CustomJDABuilder { + actions.add { it.setIdle(idle) } + return this + } + + fun setActivity(activity: Activity?): CustomJDABuilder { + actions.add { it.setActivity(activity) } + return this + } + + fun setStatus(status: OnlineStatus): CustomJDABuilder { + actions.add { it.setStatus(status) } + return this + } + + fun addEventListeners(vararg listeners: Any): CustomJDABuilder { + actions.add { it.addEventListeners(*listeners) } + return this + } + + fun removeEventListeners(vararg listeners: Any): CustomJDABuilder { + actions.add { it.removeEventListeners(*listeners) } + return this + } + + fun setMaxReconnectDelay(maxReconnectDelay: Int): CustomJDABuilder { + actions.add { it.setMaxReconnectDelay(maxReconnectDelay) } + return this + } + + fun useSharding(shardId: Int, shardTotal: Int): CustomJDABuilder { + actions.add { it.useSharding(shardId, shardTotal) } + return this + } + + fun setSessionController(controller: SessionController?): CustomJDABuilder { + actions.add { it.setSessionController(controller) } + return this + } + + fun setVoiceDispatchInterceptor(interceptor: VoiceDispatchInterceptor?): CustomJDABuilder { + actions.add { it.setVoiceDispatchInterceptor(interceptor) } + return this + } + + fun setChunkingFilter(filter: ChunkingFilter?): CustomJDABuilder { + actions.add { it.setChunkingFilter(filter) } + return this + } + + fun setDisabledIntents(intent: GatewayIntent, vararg intents: GatewayIntent): CustomJDABuilder { + actions.add { it.setDisabledIntents(intent, *intents) } + return this + } + + fun setDisabledIntents(intents: Collection?): CustomJDABuilder { + actions.add { it.setDisabledIntents(intents) } + return this + } + + fun disableIntents(intents: Collection): CustomJDABuilder { + actions.add { it.disableIntents(intents) } + return this + } + + fun disableIntents(intent: GatewayIntent, vararg intents: GatewayIntent): CustomJDABuilder { + actions.add { it.disableIntents(intent, *intents) } + return this + } + + fun setEnabledIntents(intent: GatewayIntent, vararg intents: GatewayIntent): CustomJDABuilder { + actions.add { it.setEnabledIntents(intent, *intents) } + return this + } + + fun setEnabledIntents(intents: Collection?): CustomJDABuilder { + actions.add { it.setEnabledIntents(intents) } + return this + } + + fun enableIntents(intents: Collection): CustomJDABuilder { + actions.add { it.enableIntents(intents) } + return this + } + + fun enableIntents(intent: GatewayIntent, vararg intents: GatewayIntent): CustomJDABuilder { + actions.add { it.enableIntents(intent, *intents) } + return this + } + + fun setLargeThreshold(threshold: Int): CustomJDABuilder { + actions.add { it.setLargeThreshold(threshold) } + return this + } + + fun setMaxBufferSize(bufferSize: Int): CustomJDABuilder { + actions.add { it.setMaxBufferSize(bufferSize) } + return this + } + + fun getBuilder(): JDABuilder { + val builder = creation(Unit) + actions.forEach { it(builder) } + return builder + } +} \ No newline at end of file