From 94dc6b5b48ff0f4ea23e6e1ea616881f438af825 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jul 2023 08:02:02 +0000 Subject: [PATCH 01/15] Bump mongodb-driver-sync from 4.9.1 to 4.10.2 Bumps [mongodb-driver-sync](https://github.com/mongodb/mongo-java-driver) from 4.9.1 to 4.10.2. - [Release notes](https://github.com/mongodb/mongo-java-driver/releases) - [Commits](https://github.com/mongodb/mongo-java-driver/compare/r4.9.1...r4.10.2) --- updated-dependencies: - dependency-name: org.mongodb:mongodb-driver-sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f66606b4..d51b9b20 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ org.mongodb mongodb-driver-sync - 4.9.1 + 4.10.2 com.github.walkyst From 7f8194018888c50c108edc92c2e55b721388ff4d Mon Sep 17 00:00:00 2001 From: bombies Date: Fri, 15 Sep 2023 17:18:20 -0500 Subject: [PATCH 02/15] Fix JSON serialization with log channel ids --- .../mongodb/cache/redis/guild/GuildDatabaseModel.kt | 2 +- src/main/kotlin/main/utils/json/logs/LogConfig.kt | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/main/utils/database/mongodb/cache/redis/guild/GuildDatabaseModel.kt b/src/main/kotlin/main/utils/database/mongodb/cache/redis/guild/GuildDatabaseModel.kt index 2c48843b..79f74128 100644 --- a/src/main/kotlin/main/utils/database/mongodb/cache/redis/guild/GuildDatabaseModel.kt +++ b/src/main/kotlin/main/utils/database/mongodb/cache/redis/guild/GuildDatabaseModel.kt @@ -24,7 +24,7 @@ data class GuildDatabaseModel( var theme: String = RobertifyTheme.GREEN.name.lowercase(), var autoplay: Boolean = false, var twenty_four_seven_mode: Boolean = false, - var log_channel: Long = -1, + var log_channel: Long? = -1, var locale: String = RobertifyLocale.ENGLISH.name.lowercase() ) : JsonObjectTransferable { diff --git a/src/main/kotlin/main/utils/json/logs/LogConfig.kt b/src/main/kotlin/main/utils/json/logs/LogConfig.kt index 362371e7..0ae520a8 100644 --- a/src/main/kotlin/main/utils/json/logs/LogConfig.kt +++ b/src/main/kotlin/main/utils/json/logs/LogConfig.kt @@ -1,6 +1,7 @@ package main.utils.json.logs import main.main.Robertify +import main.utils.GeneralUtils.isNotNull import main.utils.json.AbstractGuildConfig import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.channel.concrete.TextChannel @@ -10,10 +11,10 @@ import java.util.* class LogConfig(private val guild: Guild) : AbstractGuildConfig(guild) { - suspend fun getChannelId(): Long { + private suspend fun getChannelId(): Long? { if (!channelIsSet()) throw NullPointerException("There is no channel for this guild! (ID=${guild.id})") - return getGuildModel().log_channel!! + return getGuildModel().log_channel } suspend fun setChannelId(cid: Long) { @@ -23,7 +24,8 @@ class LogConfig(private val guild: Guild) : AbstractGuildConfig(guild) { } suspend fun getChannel(): TextChannel? { - return Robertify.shardManager.getTextChannelById(getChannelId()) + val channelId = getChannelId() + return channelId?.let { Robertify.shardManager.getTextChannelById(it) } } suspend fun channelIsSet(): Boolean { From 16031c8edbee96f810171e8f151ecafe02d69698 Mon Sep 17 00:00:00 2001 From: bombies Date: Fri, 15 Sep 2023 17:39:33 -0500 Subject: [PATCH 03/15] Update coroutine timeout duration --- src/main/kotlin/main/main/Robertify.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/main/main/Robertify.kt b/src/main/kotlin/main/main/Robertify.kt index 9b488870..8fb257d4 100644 --- a/src/main/kotlin/main/main/Robertify.kt +++ b/src/main/kotlin/main/main/Robertify.kt @@ -46,6 +46,7 @@ import org.quartz.SchedulerException import org.quartz.impl.StdSchedulerFactory import org.yaml.snakeyaml.reader.ReaderException import java.util.* +import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds object Robertify { @@ -113,7 +114,7 @@ object Robertify { val (dispatcher, supervisor, handler) = GeneralUtils.generateHandleCoroutineContextComponents() val context = dispatcher + supervisor + handler val scope = CoroutineScope(context) - coroutineEventManager = CoroutineEventManager(scope, 30.seconds) + coroutineEventManager = CoroutineEventManager(scope, 3.minutes) coroutineEventManager.handleShardReady() coroutineEventManager.handleGuildReady() coroutineEventManager.listener { From 86f446e1ec9bb0a954dd6011ab79becb4707d2ea Mon Sep 17 00:00:00 2001 From: bombies Date: Fri, 15 Sep 2023 17:53:05 -0500 Subject: [PATCH 04/15] Update lavakord to only be initialized when it hasn't been before. --- src/main/kotlin/main/main/Robertify.kt | 41 ++++++++++++++------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/main/kotlin/main/main/Robertify.kt b/src/main/kotlin/main/main/Robertify.kt index 8fb257d4..c892d15c 100644 --- a/src/main/kotlin/main/main/Robertify.kt +++ b/src/main/kotlin/main/main/Robertify.kt @@ -23,6 +23,7 @@ import main.events.EventManager import main.main.Listener.Companion.loadNeededSlashCommands import main.main.Listener.Companion.rescheduleUnbans import main.utils.GeneralUtils +import main.utils.GeneralUtils.isNull import main.utils.api.robertify.RobertifyApi import main.utils.component.interactions.slashcommand.AbstractSlashCommand import main.utils.database.mongodb.AbstractMongoDatabase @@ -206,29 +207,31 @@ object Robertify { BotDBCache.instance.lastStartup = System.currentTimeMillis() jda.shardManager?.setPresence(OnlineStatus.ONLINE, Activity.listening("/help")) - logger.info("Setting up LavaKord...") - val (dispatcher, supervisor, handler) = GeneralUtils.generateHandleCoroutineContextComponents() - lavaKord = shardManager.lavakord( - lavakordShardManager, dispatcher + supervisor + handler, options = MutableLavaKordOptions( - link = MutableLavaKordOptions.LinkConfig( - showTrace = true + if (!Robertify::lavaKord.isInitialized) { + logger.info("Setting up LavaKord...") + val (dispatcher, supervisor, handler) = GeneralUtils.generateHandleCoroutineContextComponents() + lavaKord = shardManager.lavakord( + lavakordShardManager, dispatcher + supervisor + handler, options = MutableLavaKordOptions( + link = MutableLavaKordOptions.LinkConfig( + showTrace = true + ) ) - ) - ) { - plugins { - install(LavaSrc) + ) { + plugins { + install(LavaSrc) + } } - } - Config.LAVA_NODES.forEach { node -> - lavaKord.addNode( - serverUri = node.uri.toString(), - password = node.password, - name = node.name - ) - logger.info("Registered lava node with address: ${node.uri}") + Config.LAVA_NODES.forEach { node -> + lavaKord.addNode( + serverUri = node.uri.toString(), + password = node.password, + name = node.name + ) + logger.info("Registered lava node with address: ${node.uri}") + } + logger.info("LavaKord ready") } - logger.info("LavaKord ready") shardManager.guildCache.forEach { guild -> RequestChannelConfig(guild).updateMessage()?.await() From 37d42c97a1f73dd9ccb197be2ebf531172145310 Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 08:16:41 -0500 Subject: [PATCH 05/15] Fix some bugs with coroutine race conditions --- .../audiohandlers/loaders/MainAudioLoader.kt | 7 +--- src/main/kotlin/main/main/Listener.kt | 2 +- src/main/kotlin/main/main/Robertify.kt | 38 +++++++------------ src/main/kotlin/main/utils/GeneralUtils.kt | 3 +- .../slashcommand/AbstractSlashCommand.kt | 10 +++-- .../database/mongodb/databases/GuildDB.kt | 15 +++++++- .../main/utils/json/AbstractGuildConfig.kt | 2 - .../RestrictedChannelsConfig.kt | 4 +- 8 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/main/kotlin/main/audiohandlers/loaders/MainAudioLoader.kt b/src/main/kotlin/main/audiohandlers/loaders/MainAudioLoader.kt index e661b3d9..36d31095 100644 --- a/src/main/kotlin/main/audiohandlers/loaders/MainAudioLoader.kt +++ b/src/main/kotlin/main/audiohandlers/loaders/MainAudioLoader.kt @@ -5,13 +5,10 @@ import dev.arbjerg.lavalink.protocol.v4.Exception import dev.arbjerg.lavalink.protocol.v4.Playlist import dev.arbjerg.lavalink.protocol.v4.Track import dev.minn.jda.ktx.coroutines.await -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import dev.minn.jda.ktx.events.getDefaultScope import kotlinx.coroutines.runBlocking import main.audiohandlers.GuildMusicManager import main.audiohandlers.models.Requester -import main.main.Robertify import main.utils.RobertifyEmbedUtils import main.utils.json.logs.LogType import main.utils.json.logs.LogUtilsKt @@ -45,7 +42,7 @@ class MainAudioLoader( private val executorService = Executors.newSingleThreadScheduledExecutor() suspend fun RestAction.queueThenDelete( - context: CoroutineContext = Robertify.coroutineEventManager.coroutineContext, + context: CoroutineContext = getDefaultScope().coroutineContext, time: Long = 10, unit: TimeUnit = TimeUnit.SECONDS, deletePredicate: (suspend (message: Message) -> Boolean)? = null, diff --git a/src/main/kotlin/main/main/Listener.kt b/src/main/kotlin/main/main/Listener.kt index 78c20873..9cabd040 100644 --- a/src/main/kotlin/main/main/Listener.kt +++ b/src/main/kotlin/main/main/Listener.kt @@ -36,7 +36,7 @@ class Listener : AbstractEventController() { * @param guild The guild to load the commands in */ internal fun loadNeededSlashCommands(guild: Guild) { - loadSlashCommands(guild) + } internal fun unloadCommands(guild: Guild, vararg commandNames: String) { diff --git a/src/main/kotlin/main/main/Robertify.kt b/src/main/kotlin/main/main/Robertify.kt index c892d15c..57c3ef04 100644 --- a/src/main/kotlin/main/main/Robertify.kt +++ b/src/main/kotlin/main/main/Robertify.kt @@ -6,6 +6,8 @@ import com.adamratzman.spotify.SpotifyAppApi import com.adamratzman.spotify.spotifyAppApi import com.google.common.util.concurrent.ThreadFactoryBuilder import dev.minn.jda.ktx.events.CoroutineEventManager +import dev.minn.jda.ktx.events.listener +import dev.minn.jda.ktx.jdabuilder.injectKTX import dev.minn.jda.ktx.util.SLF4J import dev.schlaubi.lavakord.LavaKord import dev.schlaubi.lavakord.MutableLavaKordOptions @@ -62,8 +64,6 @@ object Robertify { private set lateinit var externalApi: RobertifyApi private set - lateinit var coroutineEventManager: CoroutineEventManager - private set private val lavakordShardManager = LavaKordShardManager() @@ -111,26 +111,16 @@ object Robertify { GuildRedisCache.ins.loadAllGuilds() logger.info("All guilds have been loaded into cache.") - // Setup custom coroutine event manager - val (dispatcher, supervisor, handler) = GeneralUtils.generateHandleCoroutineContextComponents() - val context = dispatcher + supervisor + handler - val scope = CoroutineScope(context) - coroutineEventManager = CoroutineEventManager(scope, 3.minutes) - coroutineEventManager.handleShardReady() - coroutineEventManager.handleGuildReady() - coroutineEventManager.listener { - supervisor.cancel() - } - // Build bot connection logger.info("Building shard manager...") + val shardManagerBuilder = DefaultShardManagerBuilder.createDefault( Config.BOT_TOKEN, listOf(GatewayIntent.GUILD_VOICE_STATES, GatewayIntent.GUILD_MESSAGE_REACTIONS), ) .apply { setShardsTotal(Config.SHARD_COUNT) - setEventManagerProvider { coroutineEventManager } + injectKTX() setBulkDeleteSplittingEnabled(false) enableCache(CacheFlag.VOICE_STATE) disableCache( @@ -168,13 +158,14 @@ object Robertify { shardManagerBuilder.applyLavakord(lavakordShardManager) shardManager = shardManagerBuilder.build() logger.info("Successfully built shard manager") + shardManager.handleShardReady() + shardManager.handleGuildReady() val slashCommandManager = SlashCommandManager shardManager.registerCommands( slashCommandManager.guildCommands .merge(slashCommandManager.globalCommands, slashCommandManager.devCommands) ) - logger.info("Registered all slash commands.") EventManager.registeredEvents @@ -201,7 +192,7 @@ object Robertify { RobertifyKtorApi.start() } - private fun CoroutineEventManager.handleShardReady() = listener { event -> + private fun ShardManager.handleShardReady() = listener { event -> val jda = event.jda logger.info("Watching ${event.guildAvailableCount} guilds on shard #${jda.shardInfo.shardId} (${event.guildUnavailableCount} unavailable)") BotDBCache.instance.lastStartup = System.currentTimeMillis() @@ -238,17 +229,14 @@ object Robertify { } } - private fun CoroutineEventManager.handleGuildReady() = listener { event -> + private fun ShardManager.handleGuildReady() = listener { event -> val guild = event.guild - launch { - val locale = LocaleConfig(guild).getLocale() - try { - LocaleManager[guild].setLocale(locale) - } catch (e: ReaderException) { - logger.error("I couldn't set the locale for ${guild.name}") - } + val locale = LocaleConfig(guild).getLocale() + try { + LocaleManager[guild].setLocale(locale) + } catch (e: ReaderException) { + logger.error("I couldn't set the locale for ${guild.name}") } - loadNeededSlashCommands(guild) rescheduleUnbans(guild) RemindersConfig(guild).scheduleReminders() diff --git a/src/main/kotlin/main/utils/GeneralUtils.kt b/src/main/kotlin/main/utils/GeneralUtils.kt index 02cfd932..f70efd45 100644 --- a/src/main/kotlin/main/utils/GeneralUtils.kt +++ b/src/main/kotlin/main/utils/GeneralUtils.kt @@ -1,6 +1,7 @@ package main.utils import dev.minn.jda.ktx.coroutines.await +import dev.minn.jda.ktx.events.getDefaultScope import kotlinx.coroutines.* import main.constants.RobertifyPermission import main.constants.RobertifyEmoji @@ -688,7 +689,7 @@ object GeneralUtils { queueAfter(duration.inWholeSeconds, TimeUnit.SECONDS, success, failure) suspend fun RestAction.queueCoroutine( - context: CoroutineContext = Robertify.coroutineEventManager.coroutineContext, + context: CoroutineContext = getDefaultScope().coroutineContext, duration: kotlin.time.Duration = kotlin.time.Duration.ZERO, onSuccess: (suspend (item: T) -> Unit)? = null ) { diff --git a/src/main/kotlin/main/utils/component/interactions/slashcommand/AbstractSlashCommand.kt b/src/main/kotlin/main/utils/component/interactions/slashcommand/AbstractSlashCommand.kt index 94dfba9c..bca97122 100644 --- a/src/main/kotlin/main/utils/component/interactions/slashcommand/AbstractSlashCommand.kt +++ b/src/main/kotlin/main/utils/component/interactions/slashcommand/AbstractSlashCommand.kt @@ -4,6 +4,7 @@ import com.influxdb.exceptions.InfluxException import dev.minn.jda.ktx.coroutines.await import dev.minn.jda.ktx.events.CoroutineEventListener import dev.minn.jda.ktx.events.listener +import dev.minn.jda.ktx.events.onCommand import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import main.audiohandlers.RobertifyAudioManager @@ -109,7 +110,7 @@ abstract class AbstractSlashCommand protected constructor(val info: SlashCommand } } .handle(ErrorResponse.MISSING_ACCESS) { - logger.warn("I wasn't update to update commands in ${guild.name}!") + logger.warn("I wasn't able update to update commands in ${guild.name}!") } ) } @@ -184,10 +185,13 @@ abstract class AbstractSlashCommand protected constructor(val info: SlashCommand } fun register(shardManager: ShardManager) { - onEvent(shardManager) { event -> + shardManager.onCommand(this.info.name) { event -> + if (event !is SlashCommandInteractionEvent) + return@onCommand + val checks = checks(event) if (!checks) - return@onEvent + return@onCommand handle(event) diff --git a/src/main/kotlin/main/utils/database/mongodb/databases/GuildDB.kt b/src/main/kotlin/main/utils/database/mongodb/databases/GuildDB.kt index df6434c6..50bdb831 100644 --- a/src/main/kotlin/main/utils/database/mongodb/databases/GuildDB.kt +++ b/src/main/kotlin/main/utils/database/mongodb/databases/GuildDB.kt @@ -8,6 +8,8 @@ import main.constants.RobertifyTheme import main.constants.Toggle import main.constants.database.RobertifyMongoDatabase import main.main.Config +import main.utils.GeneralUtils +import main.utils.GeneralUtils.isDiscordId import main.utils.database.mongodb.AbstractMongoDatabase import main.utils.database.mongodb.DocumentBuilder import main.utils.database.mongodb.cache.redis.guild.GuildDatabaseModel @@ -34,11 +36,20 @@ object GuildDB : else -> removeDocument(doc) } - fun findGuild(gid: Long): Document? = findSpecificDocument(Field.GUILD_ID, gid) + fun findGuild(gid: Long): Document? = try { + findSpecificDocument(Field.GUILD_ID, gid) + } catch (e: NoSuchElementException) { + null + } fun updateGuild(newInfo: GuildDatabaseModel) { val document = findGuild(newInfo.server_id) - ?: throw java.lang.NullPointerException("There was no document found with guild id: ${newInfo.server_id}") + ?: run { + if (newInfo.server_id.toString().isDiscordId()) { + addGuild(newInfo.server_id) + findGuild(newInfo.server_id)!! + } else throw NullPointerException("There is no guild document with ID ${newInfo.server_id} and the ID provided is an invalid Discord ID!") + } upsertDocument(document, Document.parse(newInfo.toJsonObject().toString())) } diff --git a/src/main/kotlin/main/utils/json/AbstractGuildConfig.kt b/src/main/kotlin/main/utils/json/AbstractGuildConfig.kt index ca4963ba..fe5146d5 100644 --- a/src/main/kotlin/main/utils/json/AbstractGuildConfig.kt +++ b/src/main/kotlin/main/utils/json/AbstractGuildConfig.kt @@ -24,8 +24,6 @@ abstract class AbstractGuildConfig protected constructor(private val guild: Guil abstract suspend fun update() protected suspend fun getGuildModel(): GuildDatabaseModel { - if (!guildHasInfo()) - loadGuild() return cache.getGuildModel(guild.id)!! } diff --git a/src/main/kotlin/main/utils/json/restrictedchannels/RestrictedChannelsConfig.kt b/src/main/kotlin/main/utils/json/restrictedchannels/RestrictedChannelsConfig.kt index d6c51d07..3c72e3d1 100644 --- a/src/main/kotlin/main/utils/json/restrictedchannels/RestrictedChannelsConfig.kt +++ b/src/main/kotlin/main/utils/json/restrictedchannels/RestrictedChannelsConfig.kt @@ -50,8 +50,8 @@ class RestrictedChannelsConfig(private val guild: Guild) : AbstractGuildConfig(g suspend fun getRestrictedChannels(type: ChannelType?): List { val obj = getGuildModel().restricted_channels return when (type) { - ChannelType.TEXT_CHANNEL -> obj?.text_channels ?: emptyList() - ChannelType.VOICE_CHANNEL -> obj?.voice_channels ?: emptyList() + ChannelType.TEXT_CHANNEL -> obj.text_channels + ChannelType.VOICE_CHANNEL -> obj.voice_channels else -> throw IllegalArgumentException("Invalid type!") } } From dab4b7c1956ffdbb84308e9072952f8becc5741b Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 08:35:15 -0500 Subject: [PATCH 06/15] Fix bug with adding restricted channels --- .../database/mongodb/cache/redis/guild/GuildRedisCache.kt | 5 ++--- .../json/restrictedchannels/RestrictedChannelsConfig.kt | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/main/utils/database/mongodb/cache/redis/guild/GuildRedisCache.kt b/src/main/kotlin/main/utils/database/mongodb/cache/redis/guild/GuildRedisCache.kt index 79e34be5..09bf13ee 100644 --- a/src/main/kotlin/main/utils/database/mongodb/cache/redis/guild/GuildRedisCache.kt +++ b/src/main/kotlin/main/utils/database/mongodb/cache/redis/guild/GuildRedisCache.kt @@ -67,7 +67,7 @@ class GuildRedisCache private constructor() : DatabaseRedisCache("ROBERTIFY_GUIL val handleRestrictedChannels: (arr: JSONArray) -> JSONArray = { arr -> val newArr = JSONArray() if (!arr.isEmpty && arr[0] is Long) { - rtc.toList().forEach { item: Any -> + arr.toList().forEach { item: Any -> if (item.toString().isDiscordId()) newArr.put(item.toString()) } @@ -138,11 +138,10 @@ class GuildRedisCache private constructor() : DatabaseRedisCache("ROBERTIFY_GUIL ) } } - return obj } - fun correctGuildObj(obj: JSONObject?): JSONObject { + private fun correctGuildObj(obj: JSONObject?): JSONObject { if (!obj!!.has(GuildDB.Field.GUILD_ID.toString())) return obj if (obj.has("_id")) obj.remove("_id") if (obj.has("__v")) obj.remove("__v") diff --git a/src/main/kotlin/main/utils/json/restrictedchannels/RestrictedChannelsConfig.kt b/src/main/kotlin/main/utils/json/restrictedchannels/RestrictedChannelsConfig.kt index 3c72e3d1..59fa020b 100644 --- a/src/main/kotlin/main/utils/json/restrictedchannels/RestrictedChannelsConfig.kt +++ b/src/main/kotlin/main/utils/json/restrictedchannels/RestrictedChannelsConfig.kt @@ -1,11 +1,15 @@ package main.utils.json.restrictedchannels +import dev.minn.jda.ktx.util.SLF4J import main.utils.database.mongodb.databases.GuildDB import main.utils.json.AbstractGuildConfig import main.utils.json.getIndexOfObjectInArray import net.dv8tion.jda.api.entities.Guild class RestrictedChannelsConfig(private val guild: Guild) : AbstractGuildConfig(guild) { + companion object { + private val logger by SLF4J + } suspend fun addChannel(channelID: Long, type: ChannelType?) { val configField: GuildDB.Field = when (type) { From cc9c33c0245310654aa5d847a6f0e04bef29423d Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 09:15:12 -0500 Subject: [PATCH 07/15] Remove await call for request channel updates --- .../audiohandlers/loaders/AutoPlayLoader.kt | 1 - .../kotlin/main/events/VoiceChannelEvents.kt | 83 ++++++++++--------- src/main/kotlin/main/main/Robertify.kt | 53 ++++++------ 3 files changed, 70 insertions(+), 67 deletions(-) diff --git a/src/main/kotlin/main/audiohandlers/loaders/AutoPlayLoader.kt b/src/main/kotlin/main/audiohandlers/loaders/AutoPlayLoader.kt index 41a91b8d..fbd59f73 100644 --- a/src/main/kotlin/main/audiohandlers/loaders/AutoPlayLoader.kt +++ b/src/main/kotlin/main/audiohandlers/loaders/AutoPlayLoader.kt @@ -4,7 +4,6 @@ import com.sedmelluq.discord.lavaplayer.tools.FriendlyException import dev.arbjerg.lavalink.protocol.v4.Playlist import dev.arbjerg.lavalink.protocol.v4.Track import dev.minn.jda.ktx.util.SLF4J -import kotlinx.coroutines.runBlocking import main.audiohandlers.GuildMusicManager import main.audiohandlers.loaders.MainAudioLoader.Companion.queueThenDelete import main.audiohandlers.utils.identifier diff --git a/src/main/kotlin/main/events/VoiceChannelEvents.kt b/src/main/kotlin/main/events/VoiceChannelEvents.kt index 788951da..8ce432cd 100644 --- a/src/main/kotlin/main/events/VoiceChannelEvents.kt +++ b/src/main/kotlin/main/events/VoiceChannelEvents.kt @@ -2,6 +2,7 @@ package main.events import dev.minn.jda.ktx.util.SLF4J import main.audiohandlers.RobertifyAudioManager +import main.main.Robertify import main.utils.json.guildconfig.GuildConfig import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent @@ -12,48 +13,52 @@ class VoiceChannelEvents : AbstractEventController() { private val onGuildVoiceUpdate = onEvent { event -> - val guild = event.guild - val channelLeft = event.channelLeft - val channelJoined = event.channelJoined - val self = guild.selfMember - val selfVoiceState = self.voiceState!! - val guildMusicManager = RobertifyAudioManager[guild] - - // If the bot has left voice channels entirely - if (event.member.id == self.id && (channelLeft != null && channelJoined == null)) - return@onEvent guildMusicManager.clear() - - if (!selfVoiceState.inAudioChannel()) - return@onEvent - - val guildConfig = GuildConfig(guild) - val guildDisconnector = guildMusicManager.scheduler.disconnectManager - - /* - * If the user left voice channels entirely or - * switched and the channel left is empty we want to - * disconnect the bot unless 24/7 mode is enabled. - */ - if ( - ((channelJoined == null && channelLeft != null) || (channelJoined != null && channelLeft != null)) - && channelLeft.id == selfVoiceState.channel!!.id - ) { - if (guildConfig.getTwentyFourSevenMode() || guildDisconnector.disconnectScheduled() || channelLeft.members.size > 1) + try { + val guild = event.guild + val channelLeft = event.channelLeft + val channelJoined = event.channelJoined + val self = guild.selfMember + val selfVoiceState = self.voiceState!! + val guildMusicManager = RobertifyAudioManager[guild] + + // If the bot has left voice channels entirely + if (event.member.id == self.id && (channelLeft != null && channelJoined == null)) + return@onEvent guildMusicManager.clear() + + if (!selfVoiceState.inAudioChannel()) return@onEvent - guildMusicManager.player.pause(true) - guildDisconnector.scheduleDisconnect() - } - /* - * If the user is joining a voice channel for the - * first time and the bot is awaiting disconnect, - * cancel the disconnect and resume playing the song if - * the song is paused. - */ - else if (channelJoined != null && channelJoined.id == selfVoiceState.channel!!.id && guildDisconnector.disconnectScheduled()) { - guildDisconnector.cancelDisconnect() - guildMusicManager.player.pause(false) + val guildConfig = GuildConfig(guild) + val guildDisconnector = guildMusicManager.scheduler.disconnectManager + + /* + * If the user left voice channels entirely or + * switched and the channel left is empty we want to + * disconnect the bot unless 24/7 mode is enabled. + */ + if ( + ((channelJoined == null && channelLeft != null) || (channelJoined != null && channelLeft != null)) + && channelLeft.id == selfVoiceState.channel!!.id + ) { + if (guildConfig.getTwentyFourSevenMode() || guildDisconnector.disconnectScheduled() || channelLeft.members.size > 1) + return@onEvent + guildMusicManager.player.pause(true) + guildDisconnector.scheduleDisconnect() + } + + /* + * If the user is joining a voice channel for the + * first time and the bot is awaiting disconnect, + * cancel the disconnect and resume playing the song if + * the song is paused. + */ + else if (channelJoined != null && channelJoined.id == selfVoiceState.channel!!.id && guildDisconnector.disconnectScheduled()) { + guildDisconnector.cancelDisconnect() + guildMusicManager.player.pause(false) + } + } catch (e: UninitializedPropertyAccessException) { + logger.warn("Tried handling voice channel events before LavaKord was setup!") } } } \ No newline at end of file diff --git a/src/main/kotlin/main/main/Robertify.kt b/src/main/kotlin/main/main/Robertify.kt index 57c3ef04..b1cd55b5 100644 --- a/src/main/kotlin/main/main/Robertify.kt +++ b/src/main/kotlin/main/main/Robertify.kt @@ -6,6 +6,7 @@ import com.adamratzman.spotify.SpotifyAppApi import com.adamratzman.spotify.spotifyAppApi import com.google.common.util.concurrent.ThreadFactoryBuilder import dev.minn.jda.ktx.events.CoroutineEventManager +import dev.minn.jda.ktx.events.getDefaultScope import dev.minn.jda.ktx.events.listener import dev.minn.jda.ktx.jdabuilder.injectKTX import dev.minn.jda.ktx.util.SLF4J @@ -158,6 +159,30 @@ object Robertify { shardManagerBuilder.applyLavakord(lavakordShardManager) shardManager = shardManagerBuilder.build() logger.info("Successfully built shard manager") + + logger.info("Setting up LavaKord...") + lavaKord = shardManager.lavakord( + lavakordShardManager, getDefaultScope().coroutineContext, options = MutableLavaKordOptions( + link = MutableLavaKordOptions.LinkConfig( + showTrace = true + ) + ) + ) { + plugins { + install(LavaSrc) + } + } + + Config.LAVA_NODES.forEach { node -> + lavaKord.addNode( + serverUri = node.uri.toString(), + password = node.password, + name = node.name + ) + logger.info("Registered lava node with address: ${node.uri}") + } + logger.info("LavaKord ready") + shardManager.handleShardReady() shardManager.handleGuildReady() @@ -198,34 +223,8 @@ object Robertify { BotDBCache.instance.lastStartup = System.currentTimeMillis() jda.shardManager?.setPresence(OnlineStatus.ONLINE, Activity.listening("/help")) - if (!Robertify::lavaKord.isInitialized) { - logger.info("Setting up LavaKord...") - val (dispatcher, supervisor, handler) = GeneralUtils.generateHandleCoroutineContextComponents() - lavaKord = shardManager.lavakord( - lavakordShardManager, dispatcher + supervisor + handler, options = MutableLavaKordOptions( - link = MutableLavaKordOptions.LinkConfig( - showTrace = true - ) - ) - ) { - plugins { - install(LavaSrc) - } - } - - Config.LAVA_NODES.forEach { node -> - lavaKord.addNode( - serverUri = node.uri.toString(), - password = node.password, - name = node.name - ) - logger.info("Registered lava node with address: ${node.uri}") - } - logger.info("LavaKord ready") - } - shardManager.guildCache.forEach { guild -> - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage()?.start() } } From e6bf4b04673aed5481fe1051d3ab4d9d0719e923 Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 09:58:48 -0500 Subject: [PATCH 08/15] Remove coroutine launch for updating request channel message --- .../main/audiohandlers/GuildMusicManager.kt | 2 +- .../main/audiohandlers/TrackScheduler.kt | 4 +- .../audiohandlers/loaders/AutoPlayLoader.kt | 2 +- .../audiohandlers/loaders/MainAudioLoader.kt | 2 +- .../slashcommands/audio/MoveCommand.kt | 2 +- .../audio/PreviousTrackCommand.kt | 2 +- .../slashcommands/audio/RemoveCommand.kt | 4 +- .../slashcommands/audio/ShuffleCommand.kt | 2 +- .../slashcommands/audio/SkipCommand.kt | 2 +- .../slashcommands/audio/VolumeCommand.kt | 2 +- .../slashcommands/dev/UpdateCommand.kt | 2 +- .../slashcommands/management/ThemeCommand.kt | 2 +- .../RequestChannelEditCommand.kt | 2 +- src/main/kotlin/main/main/Robertify.kt | 2 +- .../requestchannel/RequestChannelConfig.kt | 204 +++++++++--------- 15 files changed, 114 insertions(+), 122 deletions(-) diff --git a/src/main/kotlin/main/audiohandlers/GuildMusicManager.kt b/src/main/kotlin/main/audiohandlers/GuildMusicManager.kt index 949eca0d..0139cad9 100644 --- a/src/main/kotlin/main/audiohandlers/GuildMusicManager.kt +++ b/src/main/kotlin/main/audiohandlers/GuildMusicManager.kt @@ -26,7 +26,7 @@ class GuildMusicManager(val guild: Guild) { scheduler.clearRequesters() SkipCommand().clearVoteSkipInfo(guild) - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() } suspend fun leave() { diff --git a/src/main/kotlin/main/audiohandlers/TrackScheduler.kt b/src/main/kotlin/main/audiohandlers/TrackScheduler.kt index 4eda14ec..b9d990ee 100644 --- a/src/main/kotlin/main/audiohandlers/TrackScheduler.kt +++ b/src/main/kotlin/main/audiohandlers/TrackScheduler.kt @@ -137,7 +137,7 @@ class TrackScheduler(private val guild: Guild, private val link: Link) { } val requestChannelConfig = RequestChannelConfig(guild) - requestChannelConfig.updateMessage()?.await() + requestChannelConfig.updateMessage() disconnectManager.cancelDisconnect() queueHandler.lastPlayedTrackBuffer = track @@ -244,7 +244,7 @@ class TrackScheduler(private val guild: Guild, private val link: Link) { nextTrack(trackToUse) } else { if (queueHandler.isEmpty) - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() } } diff --git a/src/main/kotlin/main/audiohandlers/loaders/AutoPlayLoader.kt b/src/main/kotlin/main/audiohandlers/loaders/AutoPlayLoader.kt index fbd59f73..322eb776 100644 --- a/src/main/kotlin/main/audiohandlers/loaders/AutoPlayLoader.kt +++ b/src/main/kotlin/main/audiohandlers/loaders/AutoPlayLoader.kt @@ -61,7 +61,7 @@ class AutoPlayLoader( queueHandler.clearSavedQueue() } - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() } override suspend fun onSearchResultLoad(results: List) { diff --git a/src/main/kotlin/main/audiohandlers/loaders/MainAudioLoader.kt b/src/main/kotlin/main/audiohandlers/loaders/MainAudioLoader.kt index 36d31095..dd01775d 100644 --- a/src/main/kotlin/main/audiohandlers/loaders/MainAudioLoader.kt +++ b/src/main/kotlin/main/audiohandlers/loaders/MainAudioLoader.kt @@ -185,7 +185,7 @@ class MainAudioLoader( if (queueHandler.queueRepeating) queueHandler.setSavedQueue(queueHandler.contents) - requestChannelConfig.updateMessage()?.await() + requestChannelConfig.updateMessage() } override suspend fun onNoMatches() { diff --git a/src/main/kotlin/main/commands/slashcommands/audio/MoveCommand.kt b/src/main/kotlin/main/commands/slashcommands/audio/MoveCommand.kt index cac87e04..c159beef 100644 --- a/src/main/kotlin/main/commands/slashcommands/audio/MoveCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/audio/MoveCommand.kt @@ -103,7 +103,7 @@ class MoveCommand : AbstractSlashCommand( ).build() } - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() val movedTrack = trackList[id - 1] LogUtilsKt(guild).sendLog( diff --git a/src/main/kotlin/main/commands/slashcommands/audio/PreviousTrackCommand.kt b/src/main/kotlin/main/commands/slashcommands/audio/PreviousTrackCommand.kt index ca4069c8..1edd9d85 100644 --- a/src/main/kotlin/main/commands/slashcommands/audio/PreviousTrackCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/audio/PreviousTrackCommand.kt @@ -47,7 +47,7 @@ class PreviousTrackCommand : AbstractSlashCommand( player.stopTrack() player.playTrack(queueHandler.popPreviousTrack()!!) - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() LogUtilsKt(guild).sendLog( LogType.TRACK_PREVIOUS, diff --git a/src/main/kotlin/main/commands/slashcommands/audio/RemoveCommand.kt b/src/main/kotlin/main/commands/slashcommands/audio/RemoveCommand.kt index dbae88ef..c2e37a78 100644 --- a/src/main/kotlin/main/commands/slashcommands/audio/RemoveCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/audio/RemoveCommand.kt @@ -115,7 +115,7 @@ class RemoveCommand : AbstractSlashCommand( Pair("{author}", removedTrack.author) ) if (id <= 10) - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() RobertifyEmbedUtils.embedMessage( guild, RemoveMessages.REMOVED, @@ -167,7 +167,7 @@ class RemoveCommand : AbstractSlashCommand( Pair("{author}", removedTrack.author) ) if (id < 10) - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() RobertifyEmbedUtils.embedMessage( guild, RemoveMessages.REMOVED, diff --git a/src/main/kotlin/main/commands/slashcommands/audio/ShuffleCommand.kt b/src/main/kotlin/main/commands/slashcommands/audio/ShuffleCommand.kt index 0904e1f5..b7a83bea 100644 --- a/src/main/kotlin/main/commands/slashcommands/audio/ShuffleCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/audio/ShuffleCommand.kt @@ -42,7 +42,7 @@ class ShuffleCommand : AbstractSlashCommand( queueHandler.clear() queueHandler.addAll(trackList) - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() LogUtilsKt(guild).sendLog( LogType.QUEUE_SHUFFLE, diff --git a/src/main/kotlin/main/commands/slashcommands/audio/SkipCommand.kt b/src/main/kotlin/main/commands/slashcommands/audio/SkipCommand.kt index 11818286..5e2f6842 100644 --- a/src/main/kotlin/main/commands/slashcommands/audio/SkipCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/audio/SkipCommand.kt @@ -138,7 +138,7 @@ class SkipCommand : AbstractSlashCommand( queueHandler.pushPastTrack(playingTrack) scheduler.nextTrack(playingTrack, true, player.position) - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() SkipCommand().clearVoteSkipInfo(guild) return RobertifyEmbedUtils.embedMessage(musicManager.guild, "Skipped to **track #$id**!").build() } diff --git a/src/main/kotlin/main/commands/slashcommands/audio/VolumeCommand.kt b/src/main/kotlin/main/commands/slashcommands/audio/VolumeCommand.kt index a16bd814..b7358774 100644 --- a/src/main/kotlin/main/commands/slashcommands/audio/VolumeCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/audio/VolumeCommand.kt @@ -62,7 +62,7 @@ class VolumeCommand : AbstractSlashCommand( this.volume = volume / 100F } - RequestChannelConfig(guild).updateMessage()?.await() + RequestChannelConfig(guild).updateMessage() LogUtilsKt(guild).sendLog( LogType.VOLUME_CHANGE, diff --git a/src/main/kotlin/main/commands/slashcommands/dev/UpdateCommand.kt b/src/main/kotlin/main/commands/slashcommands/dev/UpdateCommand.kt index 9713e566..33185d31 100644 --- a/src/main/kotlin/main/commands/slashcommands/dev/UpdateCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/dev/UpdateCommand.kt @@ -109,7 +109,7 @@ class UpdateCommand : AbstractSlashCommand( successMsg = "Successfully updated all request channel messages!", errorMsg = "Could not update all request channel messages!" ) { - it.updateMessage()?.await() + it.updateMessage() } } diff --git a/src/main/kotlin/main/commands/slashcommands/management/ThemeCommand.kt b/src/main/kotlin/main/commands/slashcommands/management/ThemeCommand.kt index 7c309041..cf9f3edc 100644 --- a/src/main/kotlin/main/commands/slashcommands/management/ThemeCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/management/ThemeCommand.kt @@ -99,7 +99,7 @@ class ThemeCommand : AbstractSlashCommand( suspend fun updateTheme(guild: Guild, theme: RobertifyTheme, shardManager: ShardManager = Robertify.shardManager) { ThemesConfig(guild).setTheme(theme) GeneralUtils.setDefaultEmbed(guild) - RequestChannelConfig(guild, shardManager).updateMessage()?.await() + RequestChannelConfig(guild, shardManager).updateMessage() } private suspend fun getSelectMenu(guild: Guild, userId: Long): StringSelectMenu { diff --git a/src/main/kotlin/main/commands/slashcommands/management/requestchannel/RequestChannelEditCommand.kt b/src/main/kotlin/main/commands/slashcommands/management/requestchannel/RequestChannelEditCommand.kt index 33650659..6f2d4b33 100644 --- a/src/main/kotlin/main/commands/slashcommands/management/requestchannel/RequestChannelEditCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/management/requestchannel/RequestChannelEditCommand.kt @@ -132,7 +132,7 @@ class RequestChannelEditCommand : AbstractSlashCommand( try { if (RobertifyAudioManager[guild].player.playingTrack != null) - config.updateMessage()?.await() + config.updateMessage() } catch (_: UninitializedPropertyAccessException) { } diff --git a/src/main/kotlin/main/main/Robertify.kt b/src/main/kotlin/main/main/Robertify.kt index b1cd55b5..c27ca59e 100644 --- a/src/main/kotlin/main/main/Robertify.kt +++ b/src/main/kotlin/main/main/Robertify.kt @@ -224,7 +224,7 @@ object Robertify { jda.shardManager?.setPresence(OnlineStatus.ONLINE, Activity.listening("/help")) shardManager.guildCache.forEach { guild -> - RequestChannelConfig(guild).updateMessage()?.start() + RequestChannelConfig(guild).updateMessage() } } diff --git a/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt b/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt index 6e954e01..40b4821c 100644 --- a/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt +++ b/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt @@ -1,10 +1,7 @@ package main.utils.json.requestchannel import dev.minn.jda.ktx.coroutines.await -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.* import kotlinx.serialization.json.Json import main.audiohandlers.RobertifyAudioManager import main.audiohandlers.utils.artworkUrl @@ -192,34 +189,33 @@ class RequestChannelConfig(private val guild: Guild, private val shardManager: S else -> getChannelId() == channel.idLong } - suspend fun updateMessage(): Deferred? = coroutineScope { + suspend fun updateMessage(): Unit = coroutineScope { logger.debug("Channel set in ${guild.name} (${guild.idLong}): ${isChannelSet()}") - if (!isChannelSet()) return@coroutineScope null - - val job = async { - val msgRequest: RestAction = getMessageRequest() ?: return@async - val musicManager = RobertifyAudioManager[guild] - val audioPlayer = musicManager.player - val playingTrack = audioPlayer.playingTrack - val queueHandler = musicManager.scheduler.queueHandler - val queueAsList = ArrayList(queueHandler.contents) - - val theme = ThemesConfig(guild).getTheme() - val localeManager = LocaleManager[guild] - val eb = EmbedBuilder() - - if (playingTrack == null) { - eb.setColor(theme.color) - eb.setTitle(localeManager.getMessage(DedicatedChannelMessages.DEDICATED_CHANNEL_NOTHING_PLAYING)) - eb.setImage(theme.idleBanner) - val scheduler = musicManager.scheduler - val announcementChannel: GuildMessageChannel? = scheduler.announcementChannel - try { - val msg = msgRequest.await() - msg.editMessage(localeManager.getMessage(DedicatedChannelMessages.DEDICATED_CHANNEL_QUEUE_NOTHING_PLAYING)) - .setEmbeds(eb.build()) - .await() - // TODO: Handle unknown message error properly + if (!isChannelSet()) return@coroutineScope + + val msgRequest: RestAction = getMessageRequest() ?: return@coroutineScope + val musicManager = RobertifyAudioManager[guild] + val audioPlayer = musicManager.player + val playingTrack = audioPlayer.playingTrack + val queueHandler = musicManager.scheduler.queueHandler + val queueAsList = ArrayList(queueHandler.contents) + + val theme = ThemesConfig(guild).getTheme() + val localeManager = LocaleManager[guild] + val eb = EmbedBuilder() + + if (playingTrack == null) { + eb.setColor(theme.color) + eb.setTitle(localeManager.getMessage(DedicatedChannelMessages.DEDICATED_CHANNEL_NOTHING_PLAYING)) + eb.setImage(theme.idleBanner) + val scheduler = musicManager.scheduler + val announcementChannel: GuildMessageChannel? = scheduler.announcementChannel + try { + val msg = msgRequest.await() + msg.editMessage(localeManager.getMessage(DedicatedChannelMessages.DEDICATED_CHANNEL_QUEUE_NOTHING_PLAYING)) + .setEmbeds(eb.build()) + .await() + // TODO: Handle unknown message error properly // msgRequest.queue( // { msg: Message -> // @@ -236,86 +232,86 @@ class RequestChannelConfig(private val guild: Guild, private val shardManager: S // ) // } // ) - } catch (e: InsufficientPermissionException) { - if (e.message!!.contains("MESSAGE_SEND")) sendEditErrorMessage(announcementChannel) - } - } else { - eb.setColor(theme.color) - eb.setTitle( - localeManager.getMessage( - DedicatedChannelMessages.DEDICATED_CHANNEL_PLAYING_EMBED_TITLE, - Pair( - "{title}", - playingTrack.title - ), - Pair( - "{author}", - playingTrack.author - ), - - Pair( - "{duration}", - GeneralUtils.formatTime(playingTrack.length) - ) + } catch (e: InsufficientPermissionException) { + if (e.message!!.contains("MESSAGE_SEND")) sendEditErrorMessage(announcementChannel) + } + } else { + eb.setColor(theme.color) + eb.setTitle( + localeManager.getMessage( + DedicatedChannelMessages.DEDICATED_CHANNEL_PLAYING_EMBED_TITLE, + Pair( + "{title}", + playingTrack.title + ), + Pair( + "{author}", + playingTrack.author + ), + + Pair( + "{duration}", + GeneralUtils.formatTime(playingTrack.length) ) ) - val requester: String = musicManager.scheduler.getRequesterAsMention(playingTrack) - eb.setDescription( - localeManager.getMessage( - NowPlayingMessages.NP_ANNOUNCEMENT_REQUESTER, - Pair("{requester}", requester) - ) + ) + val requester: String = musicManager.scheduler.getRequesterAsMention(playingTrack) + eb.setDescription( + localeManager.getMessage( + NowPlayingMessages.NP_ANNOUNCEMENT_REQUESTER, + Pair("{requester}", requester) ) + ) - eb.setImage(playingTrack.artworkUrl ?: theme.nowPlayingBanner) - eb.setFooter( - localeManager.getMessage( - DedicatedChannelMessages.DEDICATED_CHANNEL_PLAYING_EMBED_FOOTER, - Pair( - "{numSongs}", - queueAsList.size.toString() - ), - Pair( - "{volume}", - ((audioPlayer.filters.volume?.times(100) ?: 100).toInt()).toString() - ) + eb.setImage(playingTrack.artworkUrl ?: theme.nowPlayingBanner) + eb.setFooter( + localeManager.getMessage( + DedicatedChannelMessages.DEDICATED_CHANNEL_PLAYING_EMBED_FOOTER, + Pair( + "{numSongs}", + queueAsList.size.toString() + ), + Pair( + "{volume}", + ((audioPlayer.filters.volume?.times(100) ?: 100).toInt()).toString() ) ) - val nextTenSongs: StringBuilder = StringBuilder() - nextTenSongs.append("```") - if (queueAsList.size > 10) { + ) + val nextTenSongs: StringBuilder = StringBuilder() + nextTenSongs.append("```") + if (queueAsList.size > 10) { + var index = 1 + for (track in queueAsList.subList( + 0, + 10 + )) nextTenSongs.append(index++).append(". → ").append(track.title) + .append(" - ").append(track.author) + .append(" [").append(GeneralUtils.formatTime(track.length)) + .append("]\n") + } else { + if (queueHandler.isEmpty) nextTenSongs.append(localeManager.getMessage(DedicatedChannelMessages.DEDICATED_CHANNEL_QUEUE_NO_SONGS)) else { var index = 1 - for (track in queueAsList.subList( - 0, - 10 - )) nextTenSongs.append(index++).append(". → ").append(track.title) - .append(" - ").append(track.author) + for (track in queueAsList) nextTenSongs.append( + index++ + ).append(". → ").append(track.title).append(" - ").append(track.author) .append(" [").append(GeneralUtils.formatTime(track.length)) .append("]\n") - } else { - if (queueHandler.isEmpty) nextTenSongs.append(localeManager.getMessage(DedicatedChannelMessages.DEDICATED_CHANNEL_QUEUE_NO_SONGS)) else { - var index = 1 - for (track in queueAsList) nextTenSongs.append( - index++ - ).append(". → ").append(track.title).append(" - ").append(track.author) - .append(" [").append(GeneralUtils.formatTime(track.length)) - .append("]\n") - } } - nextTenSongs.append("```") - val msg = msgRequest.await() - msg.editMessage( - localeManager.getMessage( - DedicatedChannelMessages.DEDICATED_CHANNEL_QUEUE_PLAYING, - Pair( - "{songs}", - nextTenSongs.toString() - ) + } + nextTenSongs.append("```") + val msg = msgRequest.await() + msg.editMessage( + localeManager.getMessage( + DedicatedChannelMessages.DEDICATED_CHANNEL_QUEUE_PLAYING, + Pair( + "{songs}", + nextTenSongs.toString() ) ) - .setEmbeds(eb.build()) - .queue() - // TODO: Handle unknown message error properly + ) + .setEmbeds(eb.build()) + .queue() + // TODO: Handle unknown message error properly // msgRequest.queue( // { msg: Message -> // @@ -325,11 +321,8 @@ class RequestChannelConfig(private val guild: Guild, private val shardManager: S // ErrorResponse.UNKNOWN_MESSAGE // ) { removeChannel() } // ) - } - } - - return@coroutineScope job + } } private suspend fun sendEditErrorMessage(messageChannel: GuildMessageChannel?) { @@ -364,18 +357,17 @@ class RequestChannelConfig(private val guild: Guild, private val shardManager: S return try { - val messageUpdate = updateMessage() + updateMessage() val buttonUpdate = updateButtons() val topicUpdate = updateTopic() - if (messageUpdate == null || buttonUpdate == null || topicUpdate == null) { + if (buttonUpdate == null || topicUpdate == null) { logger.error( "Could not update request channel in {} because one or more of the updates resulted in a null job!", guild.name ) } else { awaitAll( - messageUpdate, buttonUpdate, topicUpdate ) From a57ae9cbf425b18f40095e3c3b027ab97ad7a3c0 Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 10:14:22 -0500 Subject: [PATCH 09/15] Implement error handling for attempting to update dedicated channels that don't exist anymore --- .../main/events/AbstractEventController.kt | 2 +- src/main/kotlin/main/main/Listener.kt | 4 --- src/main/kotlin/main/main/Robertify.kt | 1 + .../requestchannel/RequestChannelConfig.kt | 26 ++++++------------- 4 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/main/kotlin/main/events/AbstractEventController.kt b/src/main/kotlin/main/events/AbstractEventController.kt index d0195425..ea58ebb6 100644 --- a/src/main/kotlin/main/events/AbstractEventController.kt +++ b/src/main/kotlin/main/events/AbstractEventController.kt @@ -6,7 +6,7 @@ import main.main.Robertify import net.dv8tion.jda.api.events.GenericEvent import net.dv8tion.jda.api.hooks.ListenerAdapter -abstract class AbstractEventController : ListenerAdapter() { +abstract class AbstractEventController { companion object { protected val shardManager = Robertify.shardManager diff --git a/src/main/kotlin/main/main/Listener.kt b/src/main/kotlin/main/main/Listener.kt index 9cabd040..f501ec54 100644 --- a/src/main/kotlin/main/main/Listener.kt +++ b/src/main/kotlin/main/main/Listener.kt @@ -109,10 +109,6 @@ class Listener : AbstractEventController() { } } - override fun onGuildReady(event: GuildReadyEvent) { - logger.info("Guild ${event.guild.name} is ready") - } - private val guildJoinListener = onEvent { event -> val guild = event.guild diff --git a/src/main/kotlin/main/main/Robertify.kt b/src/main/kotlin/main/main/Robertify.kt index c27ca59e..faab165c 100644 --- a/src/main/kotlin/main/main/Robertify.kt +++ b/src/main/kotlin/main/main/Robertify.kt @@ -239,6 +239,7 @@ object Robertify { loadNeededSlashCommands(guild) rescheduleUnbans(guild) RemindersConfig(guild).scheduleReminders() + logger.info("${guild.name} is ready!") // GuildResumeManager(guild).loadTracks() } diff --git a/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt b/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt index 40b4821c..3a2a07d8 100644 --- a/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt +++ b/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt @@ -32,6 +32,7 @@ import net.dv8tion.jda.api.entities.MessageHistory import net.dv8tion.jda.api.entities.channel.concrete.TextChannel import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel import net.dv8tion.jda.api.exceptions.ErrorHandler +import net.dv8tion.jda.api.exceptions.ErrorResponseException import net.dv8tion.jda.api.exceptions.InsufficientPermissionException import net.dv8tion.jda.api.interactions.components.ActionRow import net.dv8tion.jda.api.interactions.components.buttons.Button @@ -181,7 +182,7 @@ class RequestChannelConfig(private val guild: Guild, private val shardManager: S suspend fun isChannelSet(): Boolean { val obj = getGuildModel().dedicated_channel - return obj != null && obj.channel_id != -1L + return obj.channel_id != -1L } suspend fun isRequestChannel(channel: GuildMessageChannel): Boolean = when { @@ -215,25 +216,14 @@ class RequestChannelConfig(private val guild: Guild, private val shardManager: S msg.editMessage(localeManager.getMessage(DedicatedChannelMessages.DEDICATED_CHANNEL_QUEUE_NOTHING_PLAYING)) .setEmbeds(eb.build()) .await() - // TODO: Handle unknown message error properly -// msgRequest.queue( -// { msg: Message -> -// -// }, -// ErrorHandler() -// .handle( -// ErrorResponse.UNKNOWN_MESSAGE -// ) { removeChannel() } -// .handle( -// ErrorResponse.MISSING_PERMISSIONS -// ) { -// sendEditErrorMessage( -// announcementChannel -// ) -// } -// ) } catch (e: InsufficientPermissionException) { if (e.message!!.contains("MESSAGE_SEND")) sendEditErrorMessage(announcementChannel) + } catch (e: ErrorResponseException) { + when (e.errorResponse) { + ErrorResponse.MISSING_PERMISSIONS -> sendEditErrorMessage(announcementChannel) + ErrorResponse.UNKNOWN_MESSAGE -> removeChannel() + else -> {} + } } } else { eb.setColor(theme.color) From 816f64ecd4b860fb8963676739e7dd563e65fcd7 Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 11:22:09 -0500 Subject: [PATCH 10/15] Fix some more bugs --- .../main/audiohandlers/RobertifyAudioManager.kt | 11 +++++++++++ src/main/kotlin/main/audiohandlers/TrackScheduler.kt | 10 ++++++++-- .../main/audiohandlers/utils/AudioTrackExtentions.kt | 5 ++++- .../commands/slashcommands/audio/NowPlayingCommand.kt | 10 ++++++++-- src/main/kotlin/main/main/Robertify.kt | 4 +++- .../utils/json/requestchannel/RequestChannelConfig.kt | 11 +++++++---- 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt b/src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt index b5bc6ba8..059347df 100644 --- a/src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt +++ b/src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt @@ -23,6 +23,7 @@ import main.utils.json.restrictedchannels.RestrictedChannelsConfig import main.utils.json.toggles.TogglesConfig import main.utils.locale.LocaleManager import main.utils.locale.messages.GeneralMessages +import main.utils.locale.messages.JoinMessages import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.GuildVoiceState import net.dv8tion.jda.api.entities.Message @@ -31,6 +32,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel import net.dv8tion.jda.api.exceptions.InsufficientPermissionException import net.dv8tion.jda.api.interactions.InteractionHook +import java.lang.IllegalArgumentException import java.util.* object RobertifyAudioManager { @@ -279,6 +281,15 @@ object RobertifyAudioManager { if (message != null) message.editMessageEmbeds(embed).queue() else hookMessage?.editEmbed { embed }?.queue() + } catch (e: IllegalArgumentException) { + val embed = RobertifyEmbedUtils.embedMessage( + channel.guild, + JoinMessages.CANT_JOIN, + Pair("{channel}", channel.asMention) + ).build() + if (message != null) + message.editMessageEmbeds(embed).queue() + else hookMessage?.editEmbed { embed }?.queue() } return false diff --git a/src/main/kotlin/main/audiohandlers/TrackScheduler.kt b/src/main/kotlin/main/audiohandlers/TrackScheduler.kt index b9d990ee..6adfc283 100644 --- a/src/main/kotlin/main/audiohandlers/TrackScheduler.kt +++ b/src/main/kotlin/main/audiohandlers/TrackScheduler.kt @@ -8,6 +8,8 @@ import dev.schlaubi.lavakord.audio.player.Player import kotlinx.coroutines.* import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.MissingFieldException import main.audiohandlers.models.Requester import main.audiohandlers.utils.artworkUrl import main.audiohandlers.utils.author @@ -114,6 +116,7 @@ class TrackScheduler(private val guild: Guild, private val link: Link) { .launchIn(player.coroutineScope) } + @OptIn(ExperimentalSerializationApi::class) private suspend fun onTrackStart(event: TrackStartEvent) { val track = event.track @@ -183,7 +186,11 @@ class TrackScheduler(private val guild: Guild, private val link: Link) { img = NowPlayingImageBuilder( artistName = track.author, title = track.title, - albumImage = track.artworkUrl ?: defaultBackgroundImage, + albumImage = try { + track.artworkUrl ?: defaultBackgroundImage + } catch (e: MissingFieldException) { + defaultBackgroundImage + }, requesterName = requesterUser.name, requesterAvatar = requesterUser.avatarUrl ).build() ?: throw NullPointerException("The generated image was null!") @@ -390,7 +397,6 @@ class TrackScheduler(private val guild: Guild, private val link: Link) { if (nextTrack != null) { logger.debug("Retrieved {} and attempting to play", nextTrack.info.title) player.playTrack(nextTrack) - } else { if (lastTrack != null && AutoPlayConfig(guild).getStatus() diff --git a/src/main/kotlin/main/audiohandlers/utils/AudioTrackExtentions.kt b/src/main/kotlin/main/audiohandlers/utils/AudioTrackExtentions.kt index 6334614e..563a9027 100644 --- a/src/main/kotlin/main/audiohandlers/utils/AudioTrackExtentions.kt +++ b/src/main/kotlin/main/audiohandlers/utils/AudioTrackExtentions.kt @@ -2,6 +2,8 @@ package main.audiohandlers.utils import dev.arbjerg.lavalink.protocol.v4.Track import dev.schlaubi.lavakord.plugins.lavasrc.lavaSrcInfo +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.MissingFieldException val Track.identifier: String get() = info.identifier @@ -24,8 +26,9 @@ val Track.uri: String? val Track.source: String get() = info.sourceName +@OptIn(ExperimentalSerializationApi::class) val Track.artworkUrl: String? - get() = info.artworkUrl ?: lavaSrcInfo.artistArtworkUrl + get() = try { info.artworkUrl ?: lavaSrcInfo.artistArtworkUrl } catch (e: MissingFieldException) { null } val Track.isrc: String? get() = info.isrc \ No newline at end of file diff --git a/src/main/kotlin/main/commands/slashcommands/audio/NowPlayingCommand.kt b/src/main/kotlin/main/commands/slashcommands/audio/NowPlayingCommand.kt index 3718182a..ce217fd8 100644 --- a/src/main/kotlin/main/commands/slashcommands/audio/NowPlayingCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/audio/NowPlayingCommand.kt @@ -2,6 +2,8 @@ package main.commands.slashcommands.audio import com.github.topisenpai.lavasrc.mirror.MirroringAudioTrack import dev.minn.jda.ktx.util.SLF4J +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.MissingFieldException import main.audiohandlers.RobertifyAudioManager import main.audiohandlers.utils.* import main.constants.Toggle @@ -37,6 +39,7 @@ class NowPlayingCommand : AbstractSlashCommand( val logger by SLF4J } + @OptIn(ExperimentalSerializationApi::class) override suspend fun handle(event: SlashCommandInteractionEvent) { event.deferReply().queue() @@ -88,8 +91,11 @@ class NowPlayingCommand : AbstractSlashCommand( val builder = NowPlayingImageBuilder( title = track!!.title, artistName = track.author, - albumImage = track.artworkUrl - ?: defaultImage + albumImage = try { + track.artworkUrl ?: defaultImage + } catch (e: MissingFieldException) { + defaultImage + } ) val image = if (!track.isStream) diff --git a/src/main/kotlin/main/main/Robertify.kt b/src/main/kotlin/main/main/Robertify.kt index faab165c..d2d712c2 100644 --- a/src/main/kotlin/main/main/Robertify.kt +++ b/src/main/kotlin/main/main/Robertify.kt @@ -131,7 +131,9 @@ object Robertify { CacheFlag.ROLE_TAGS, CacheFlag.ONLINE_STATUS, CacheFlag.STICKER, - CacheFlag.SCHEDULED_EVENTS + CacheFlag.SCHEDULED_EVENTS, + CacheFlag.MEMBER_OVERRIDES, + CacheFlag.FORUM_TAGS ) setActivity(Activity.listening("Starting up...")) diff --git a/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt b/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt index 3a2a07d8..cff37a1f 100644 --- a/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt +++ b/src/main/kotlin/main/utils/json/requestchannel/RequestChannelConfig.kt @@ -167,10 +167,13 @@ class RequestChannelConfig(private val guild: Guild, private val shardManager: S throw IllegalArgumentException( "${shardManager.getGuildById(guild.idLong)?.name} (${guild.idLong}) doesn't have a request channel set." ) - - getTextChannel() - ?.delete() - ?.queue(null, ErrorHandler().ignore(ErrorResponse.MISSING_PERMISSIONS)) + try { + getTextChannel() + ?.delete() + ?.queue(null, ErrorHandler().ignore(ErrorResponse.MISSING_PERMISSIONS)) + } catch (e: InsufficientPermissionException) { + logger.warn("Could not delete Discord request channel in ${guild.name} (${guild.idLong})") + } cache.updateGuild(guild.id) { dedicated_channel { From de9e5988700f3b57e9ddeaae12503ed14bb95c02 Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 12:00:03 -0500 Subject: [PATCH 11/15] Fix bug with joining channels while 24/7 mode is enabled --- src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt b/src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt index 059347df..0f84a660 100644 --- a/src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt +++ b/src/main/kotlin/main/audiohandlers/RobertifyAudioManager.kt @@ -217,7 +217,7 @@ object RobertifyAudioManager { hookMessage: InteractionHook? = null ): Boolean { try { - require(!GuildConfig(musicManager.guild).getTwentyFourSevenMode() && channel.members.size > 0) { "I can't join a voice channel with no one in it!" } + require(channel.members.size > 0) { "I can't join a voice channel with no one in it!" } when (musicManager.link.state) { Link.State.DESTROYED, Link.State.NOT_CONNECTED -> { val guild = musicManager.guild From 851c804d80ced4f74e5d7e760ad1039d3029b900 Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 12:14:24 -0500 Subject: [PATCH 12/15] Fix bug with interaction reply when suggestions have already been setup --- .../main/commands/slashcommands/dev/ManageSuggestionsCommand.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/main/commands/slashcommands/dev/ManageSuggestionsCommand.kt b/src/main/kotlin/main/commands/slashcommands/dev/ManageSuggestionsCommand.kt index 714824a6..8341c3dd 100644 --- a/src/main/kotlin/main/commands/slashcommands/dev/ManageSuggestionsCommand.kt +++ b/src/main/kotlin/main/commands/slashcommands/dev/ManageSuggestionsCommand.kt @@ -171,7 +171,7 @@ class ManageSuggestionsCommand : AbstractSlashCommand( event.deferReply(true).queue() if (config.suggestionSetup) - return event.replyEmbed("The suggestions channels have already been setup!") + return event.hook.sendEmbed(guild, "The suggestions channels have already been setup!") .setEphemeral(true) .queue() From c7bcfa1c1850a6e6811a8152fd47da19af343633 Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 12:29:43 -0500 Subject: [PATCH 13/15] Add a blank check for getting items from redis --- .../main/utils/database/mongodb/cache/redis/RedisCache.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/main/utils/database/mongodb/cache/redis/RedisCache.kt b/src/main/kotlin/main/utils/database/mongodb/cache/redis/RedisCache.kt index 0d1c8698..3b814e40 100644 --- a/src/main/kotlin/main/utils/database/mongodb/cache/redis/RedisCache.kt +++ b/src/main/kotlin/main/utils/database/mongodb/cache/redis/RedisCache.kt @@ -66,7 +66,8 @@ abstract class RedisCache protected constructor(cacheID: String) { } protected open suspend fun get(identifier: String): String? = coroutineScope { - return@coroutineScope jedis.get(cacheID + identifier) + val item = jedis.get(cacheID + identifier) + return@coroutineScope item.ifBlank { null } } protected open suspend fun get(identifier: Long): String? { From 90a46a44fbe11d7210845209149c7e7c2438c52d Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 16 Sep 2023 12:30:52 -0500 Subject: [PATCH 14/15] Add a nil check for getting items from redis --- .../main/utils/database/mongodb/cache/redis/RedisCache.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/main/utils/database/mongodb/cache/redis/RedisCache.kt b/src/main/kotlin/main/utils/database/mongodb/cache/redis/RedisCache.kt index 3b814e40..b3e64a82 100644 --- a/src/main/kotlin/main/utils/database/mongodb/cache/redis/RedisCache.kt +++ b/src/main/kotlin/main/utils/database/mongodb/cache/redis/RedisCache.kt @@ -67,7 +67,7 @@ abstract class RedisCache protected constructor(cacheID: String) { protected open suspend fun get(identifier: String): String? = coroutineScope { val item = jedis.get(cacheID + identifier) - return@coroutineScope item.ifBlank { null } + return@coroutineScope if (item == "nil") null else item } protected open suspend fun get(identifier: Long): String? { From b86446efca739650cefde602079596ed0e6faa29 Mon Sep 17 00:00:00 2001 From: bombies Date: Sat, 7 Oct 2023 10:21:02 -0500 Subject: [PATCH 15/15] Add some boot optimizations and handle null image generations --- .../main/audiohandlers/TrackScheduler.kt | 2 +- src/main/kotlin/main/main/Robertify.kt | 19 ++++--------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/main/audiohandlers/TrackScheduler.kt b/src/main/kotlin/main/audiohandlers/TrackScheduler.kt index 6adfc283..595f5613 100644 --- a/src/main/kotlin/main/audiohandlers/TrackScheduler.kt +++ b/src/main/kotlin/main/audiohandlers/TrackScheduler.kt @@ -197,7 +197,7 @@ class TrackScheduler(private val guild: Guild, private val link: Link) { } catch (ex: Exception) { // Either building the image failed or the bot doesn't have enough // permission to send images in a certain channel - if (ex is PermissionException || ex is ImageBuilderException) { + if (ex is PermissionException || ex is ImageBuilderException || ex is NullPointerException) { try { sendNowPlayingEmbed(trackInfo, requesterMention).await() } catch (ex: PermissionException) { diff --git a/src/main/kotlin/main/main/Robertify.kt b/src/main/kotlin/main/main/Robertify.kt index d2d712c2..9c4acc73 100644 --- a/src/main/kotlin/main/main/Robertify.kt +++ b/src/main/kotlin/main/main/Robertify.kt @@ -44,6 +44,8 @@ import net.dv8tion.jda.api.events.session.ShutdownEvent import net.dv8tion.jda.api.requests.GatewayIntent import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder import net.dv8tion.jda.api.sharding.ShardManager +import net.dv8tion.jda.api.utils.ChunkingFilter +import net.dv8tion.jda.api.utils.MemberCachePolicy import net.dv8tion.jda.api.utils.cache.CacheFlag import org.discordbots.api.client.DiscordBotListAPI import org.quartz.SchedulerException @@ -109,32 +111,19 @@ object Robertify { AbstractMongoDatabase.initAllCaches() logger.info("Initialized all caches.") - GuildRedisCache.ins.loadAllGuilds() - logger.info("All guilds have been loaded into cache.") - // Build bot connection logger.info("Building shard manager...") - val shardManagerBuilder = DefaultShardManagerBuilder.createDefault( + val shardManagerBuilder = DefaultShardManagerBuilder.createLight( Config.BOT_TOKEN, listOf(GatewayIntent.GUILD_VOICE_STATES, GatewayIntent.GUILD_MESSAGE_REACTIONS), ) .apply { setShardsTotal(Config.SHARD_COUNT) injectKTX() + setMemberCachePolicy(MemberCachePolicy.DEFAULT) setBulkDeleteSplittingEnabled(false) enableCache(CacheFlag.VOICE_STATE) - disableCache( - CacheFlag.ACTIVITY, - CacheFlag.EMOJI, - CacheFlag.CLIENT_STATUS, - CacheFlag.ROLE_TAGS, - CacheFlag.ONLINE_STATUS, - CacheFlag.STICKER, - CacheFlag.SCHEDULED_EVENTS, - CacheFlag.MEMBER_OVERRIDES, - CacheFlag.FORUM_TAGS - ) setActivity(Activity.listening("Starting up...")) val disabledIntents = mutableListOf(