/* * lilJudd * Copyright (C) 2024 moonleay * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package net.moonleay.liljudd import com.kotlindiscord.kord.extensions.ExtensibleBot import com.kotlindiscord.kord.extensions.utils.dm import dev.kord.common.entity.PresenceStatus import dev.kord.core.behavior.interaction.response.respond import dev.kord.core.event.gateway.ReadyEvent import dev.kord.core.event.interaction.ButtonInteractionCreateEvent import dev.kord.core.on import dev.kord.gateway.Intent import dev.kord.gateway.PrivilegedIntent import dev.kord.gateway.builder.Shards import dev.kord.rest.builder.message.embed import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch import net.moonleay.liljudd.build.BuildConstants import net.moonleay.liljudd.buttons.component.EditButtonManager import net.moonleay.liljudd.data.CredentialManager import net.moonleay.liljudd.data.NewsManager import net.moonleay.liljudd.data.StacktraceSaver import net.moonleay.liljudd.data.database.DB import net.moonleay.liljudd.extensions.* import net.moonleay.liljudd.features.AvailabilityManager import net.moonleay.liljudd.features.MatchManager import net.moonleay.liljudd.features.TimeManager import net.moonleay.liljudd.util.EmbedColor import net.moonleay.liljudd.util.Logger import net.moonleay.liljudd.util.MessageUtil import kotlin.system.exitProcess object Bot { //The kord object gets set at app launch lateinit var bot: ExtensibleBot private val jobs = mutableListOf() @OptIn(PrivilegedIntent::class) suspend fun start() { Logger.out("Starting Bot...") // Load config CredentialManager.load() // Don't run the bot when there is no bot token in config if (CredentialManager.token == "empty") { Logger.out("The config does not contain a bot token.") exitProcess(3) } // Check if the credentials for the Database are existent, don't run if they are missing if (CredentialManager.dbDomain == "empty" || CredentialManager.dbName == "empty" || CredentialManager.dbUser == "empty" || CredentialManager.dbPassword == "empty") { Logger.out("The config does not contain the whole Database credentials.") exitProcess(3) } if (CredentialManager.apiDomain == "empty" || CredentialManager.apiToken == "empty") { Logger.out("The config does not contain the whole API credentials.") exitProcess(3) } // Connect to the database DB.connect( CredentialManager.dbDomain, CredentialManager.dbName, CredentialManager.dbUser, CredentialManager.dbPassword ) // Make sure the database is up-to-date DB.register() // Register all the jobs jobs.addAll( listOf( TimeManager, AvailabilityManager, ).map { CoroutineScope(Dispatchers.Default).launch { it.registerThread() } } ) // Thanks silenium-dev <3 // Create the bot object bot = ExtensibleBot(CredentialManager.token) { applicationCommands { enabled = true } extensions { add(::InfoExtension) add(::FeatureManageExtension) add(::SendPlannerExtension) add(::MatchExtension) add(::UpdateRolesExtension) add(::RotationExtension) } this.presence { this.status = PresenceStatus.DoNotDisturb this.playing("v." + BuildConstants.version) } this.intents { +Intent.GuildMembers } errorResponse { _, type -> val stamp = System.currentTimeMillis() this.embed { this.title = "Oops. Something went wrong." this.description = "The bot encountered an error during execution.\n" + "Please report this to <@${BuildConstants.ownerID}>.\n" + "The errorid is \"$stamp.stk\"" this.field { this.name = "Error message:" this.value = type.error.message.toString() this.inline = false } } StacktraceSaver.saveStacktrace(type.error, stamp) } this.sharding { recommended -> Shards(recommended) } } // Register button presses bot.kordRef.on { val inter = this.interaction val u = inter.user Logger.out("Button interaction: ${inter.componentId} from ${u.asUser().username}#${u.asUser().discriminator}") if (inter.componentId.startsWith("public.edit.")) { val response = inter.deferPublicMessageUpdate() val g = this.interaction.getOriginalInteractionResponse().getGuild() for (b in EditButtonManager.buttons) { if (b.id != inter.componentId) continue b.onInteraction(inter, response, g, u) return@on } return@on } if (inter.componentId.startsWith("public.message.")) { val response = inter.deferPublicResponse() response.respond { this.embeds = mutableListOf( MessageUtil.getEmbed( EmbedColor.ERROR, "404: Not Found", "Could not find button with id \"${inter.componentId}\"." + "\nPlease report this.", u.asUser().username + "#" + u.asUser().discriminator ) ) } } } bot.kordRef.on { AvailabilityManager.runThread() // Update Availabilities MatchManager.update() // Update Matches // Load news NewsManager.load() if(NewsManager.shouldPost == "yes"){ bot.kordRef.guilds.collect { val owner = it.owner.asUser() Logger.out("Sent News to ${owner.username} from ${it.name}") owner.dm { this.embed { this.title = NewsManager.title this.description = NewsManager.news this.footer { this.icon = bot.kordRef.getSelf().avatar?.cdnUrl?.toUrl() this.text = MessageUtil.getFooter() } } } } NewsManager.shouldPost = "no" NewsManager.update() } // Make the bot update the status every 6 seconds // JobManager.addJob(StatusUpdater) } // Update the Splatoon 3 api data and make sure it stays up-to-date // Splatoon3Api.updateSchedule() // JobManager.addJob(Splatoon3ApiScheduleUpdateScheduler) /* Other caches will be added when implemented its not used yet in order to reduce load on the api, which i am using. */ // Had to disable bc of an error. // Will fix when I have time //Start the bot bot.start() } }