feat: added dynamic registering of commands & options, added embed support, added sample command
This commit is contained in:
parent
f821a06342
commit
f802445ccb
8 changed files with 339 additions and 21 deletions
|
@ -19,28 +19,107 @@
|
||||||
|
|
||||||
package de.limited_dev.botendo
|
package de.limited_dev.botendo
|
||||||
|
|
||||||
|
import de.limited_dev.botendo.commands.slash.component.SlashCommandManager
|
||||||
|
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||||
|
import de.limited_dev.botendo.commands.slash.component.options.OptionType
|
||||||
import de.limited_dev.botendo.util.Logger
|
import de.limited_dev.botendo.util.Logger
|
||||||
import de.limited_dev.botendo.util.TokenManager
|
import de.limited_dev.botendo.util.TokenManager
|
||||||
import dev.kord.core.Kord
|
import dev.kord.core.Kord
|
||||||
|
import dev.kord.core.event.interaction.GuildChatInputCommandInteractionCreateEvent
|
||||||
|
import dev.kord.core.on
|
||||||
import dev.kord.gateway.Intent
|
import dev.kord.gateway.Intent
|
||||||
import dev.kord.gateway.PrivilegedIntent
|
import dev.kord.gateway.PrivilegedIntent
|
||||||
|
import dev.kord.rest.builder.interaction.boolean
|
||||||
|
import dev.kord.rest.builder.interaction.integer
|
||||||
|
import dev.kord.rest.builder.interaction.string
|
||||||
|
|
||||||
object Bot {
|
object Bot {
|
||||||
//The kord object gets set at app launch
|
//The kord object gets set at app launch
|
||||||
var kord: Kord? = null
|
var kord: Kord? = null
|
||||||
suspend fun start() {
|
suspend fun start() {
|
||||||
|
Logger.out("Starting Bot...")
|
||||||
|
|
||||||
//Load config
|
//Load config
|
||||||
TokenManager.load()
|
TokenManager.load()
|
||||||
|
|
||||||
|
|
||||||
//Don't run the bot when there is no bot token in config
|
//Don't run the bot when there is no bot token in config
|
||||||
if (TokenManager.token == "empty") {
|
if (TokenManager.token == "empty") {
|
||||||
Logger.out("The config does not contain a bot token")
|
Logger.out("The config does not contain a bot token")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// start the bot
|
//Register slash commands to bot & Discord
|
||||||
|
SlashCommandManager.register()
|
||||||
|
|
||||||
|
//Add Bot token to kord
|
||||||
kord = Kord(TokenManager.token)
|
kord = Kord(TokenManager.token)
|
||||||
|
|
||||||
|
//Register Command Listener
|
||||||
|
kord!!.on<GuildChatInputCommandInteractionCreateEvent> {
|
||||||
|
val response = interaction.deferPublicResponse()
|
||||||
|
val command = interaction.command
|
||||||
|
Logger.out("Command /${command.rootName}")
|
||||||
|
for (c in SlashCommandManager.commands) {
|
||||||
|
if (c.name != command.rootName)
|
||||||
|
continue
|
||||||
|
val opt = mutableMapOf<CommandOption, String>()
|
||||||
|
if (c.options != null) {
|
||||||
|
for (o in c.options) {
|
||||||
|
when (o.type) {
|
||||||
|
OptionType.INT ->
|
||||||
|
if (command.integers[o.name] != null)
|
||||||
|
opt[o] = command.integers[o.name].toString()
|
||||||
|
|
||||||
|
OptionType.STRING ->
|
||||||
|
if (command.strings[o.name] != null)
|
||||||
|
opt[o] = command.strings[o.name].toString()
|
||||||
|
|
||||||
|
OptionType.BOOLEAN ->
|
||||||
|
if (command.booleans[o.name] != null)
|
||||||
|
opt[o] = command.booleans[o.name].toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.onSlashCommand(interaction, response, opt)
|
||||||
|
//response.respond { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Register Slash Commands at Discord
|
||||||
|
kord!!.createGlobalApplicationCommands {
|
||||||
|
for (sc in SlashCommandManager.commands) {
|
||||||
|
this.input(sc.name, sc.description, builder = {
|
||||||
|
if (sc.options != null) {
|
||||||
|
for (o in sc.options) {
|
||||||
|
when (o.type) {
|
||||||
|
|
||||||
|
OptionType.INT -> {
|
||||||
|
integer(o.name, o.description) {
|
||||||
|
this.required = o.required
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionType.STRING -> {
|
||||||
|
string(o.name, o.description) {
|
||||||
|
this.required = o.required
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionType.BOOLEAN -> {
|
||||||
|
boolean(o.name, o.description) {
|
||||||
|
this.required = o.required
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.out("Logging in")
|
||||||
|
|
||||||
|
//Start the bot
|
||||||
kord!!.login {
|
kord!!.login {
|
||||||
// Load gateway privileges
|
// Load gateway privileges
|
||||||
@OptIn(PrivilegedIntent::class)
|
@OptIn(PrivilegedIntent::class)
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Botendo
|
||||||
|
* Copyright (C) 2023 limited_dev
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.limited_dev.botendo.commands.slash.component
|
||||||
|
|
||||||
|
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||||
|
|
||||||
|
abstract class SlashCommand(val name: String, val description: String, val options: List<CommandOption>? = null) {
|
||||||
|
|
||||||
|
open suspend fun onSlashCommand(
|
||||||
|
interaction: GuildChatInputCommandInteraction,
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
args: Map<CommandOption, String>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,17 +17,15 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.limited_dev.botendo.commands.slash
|
package de.limited_dev.botendo.commands.slash.component
|
||||||
|
|
||||||
|
import de.limited_dev.botendo.commands.slash.util.InfoCommand
|
||||||
|
|
||||||
object SlashCommandManager {
|
object SlashCommandManager {
|
||||||
|
|
||||||
|
val commands = mutableListOf<SlashCommand>()
|
||||||
|
|
||||||
fun register() {
|
fun register() {
|
||||||
|
commands.add(InfoCommand())
|
||||||
}
|
|
||||||
|
|
||||||
fun registerAtDiscord(commands: List<SlashCommand>) {
|
|
||||||
//Bot.kord.createGlobalApplicationCommands {
|
|
||||||
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,10 +17,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.limited_dev.botendo.commands.slash
|
package de.limited_dev.botendo.commands.slash.component.options
|
||||||
|
|
||||||
abstract class SlashCommand(val name: String, val description: String, val options: Array<String>? = null) {
|
|
||||||
|
|
||||||
fun onSlashCommand() {}
|
|
||||||
|
|
||||||
|
data class CommandOption(val name: String, val description: String, val required: Boolean, val type: OptionType) {
|
||||||
}
|
}
|
|
@ -17,11 +17,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.limited_dev.botendo.util
|
package de.limited_dev.botendo.commands.slash.component.options
|
||||||
|
|
||||||
object SlashCommandListener {
|
|
||||||
|
|
||||||
fun check() {
|
|
||||||
|
|
||||||
}
|
enum class OptionType {
|
||||||
|
INT,
|
||||||
|
STRING,
|
||||||
|
BOOLEAN
|
||||||
}
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Botendo
|
||||||
|
* Copyright (C) 2023 limited_dev
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.limited_dev.botendo.commands.slash.util
|
||||||
|
|
||||||
|
import de.limited_dev.botendo.build.BuildConstants
|
||||||
|
import de.limited_dev.botendo.commands.slash.component.SlashCommand
|
||||||
|
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||||
|
import de.limited_dev.botendo.util.MessageUtil
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||||
|
|
||||||
|
class InfoCommand : SlashCommand("info", "Shows infos about the bot", null) {
|
||||||
|
override suspend fun onSlashCommand(
|
||||||
|
interaction: GuildChatInputCommandInteraction,
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
args: Map<CommandOption, String>
|
||||||
|
) {
|
||||||
|
MessageUtil.sendEmbedForInteraction(interaction, response, "Botendo v5", "ver." + BuildConstants.version)
|
||||||
|
}
|
||||||
|
}
|
84
src/main/kotlin/de/limited_dev/botendo/util/MessageUtil.kt
Normal file
84
src/main/kotlin/de/limited_dev/botendo/util/MessageUtil.kt
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Botendo
|
||||||
|
* Copyright (C) 2023 limited_dev
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.limited_dev.botendo.util
|
||||||
|
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.behavior.interaction.response.respond
|
||||||
|
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||||
|
import dev.kord.rest.builder.message.EmbedBuilder
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
object MessageUtil {
|
||||||
|
private val dtf: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy @ HH:mm:ss")
|
||||||
|
|
||||||
|
suspend fun sendEmbedForInteraction(
|
||||||
|
interaction: GuildChatInputCommandInteraction,
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
title: String,
|
||||||
|
description: String
|
||||||
|
) {
|
||||||
|
response.respond {
|
||||||
|
embeds = mutableListOf(
|
||||||
|
getEmbed(
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
interaction.user.username + "#" + interaction.user.discriminator
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun sendEmbedForInteractionWithImage(
|
||||||
|
interaction: GuildChatInputCommandInteraction,
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
title: String,
|
||||||
|
description: String,
|
||||||
|
thumbnailUrl: String
|
||||||
|
) {
|
||||||
|
response.respond {
|
||||||
|
embeds = mutableListOf(
|
||||||
|
getEmbedWithImage(
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
interaction.user.username + "#" + interaction.user.discriminator,
|
||||||
|
thumbnailUrl
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getEmbed(title: String, description: String, source: String): EmbedBuilder {
|
||||||
|
val now: LocalDateTime = LocalDateTime.now()
|
||||||
|
val ebb = EmbedBuilder()
|
||||||
|
ebb.title = title
|
||||||
|
ebb.description = description
|
||||||
|
ebb.footer = EmbedBuilder.Footer()
|
||||||
|
ebb.footer!!.text = ">" + dtf.format(now) + " - $source"
|
||||||
|
return ebb
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getEmbedWithImage(title: String, description: String, source: String, thumbnailUrl: String): EmbedBuilder {
|
||||||
|
val ebb = getEmbed(title, description, source)
|
||||||
|
ebb.thumbnail = EmbedBuilder.Thumbnail()
|
||||||
|
ebb.thumbnail!!.url = thumbnailUrl
|
||||||
|
return ebb
|
||||||
|
}
|
||||||
|
}
|
89
src/main/kotlin/de/limited_dev/botendo/util/TimeUtil.kt
Normal file
89
src/main/kotlin/de/limited_dev/botendo/util/TimeUtil.kt
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Botendo
|
||||||
|
* Copyright (C) 2023 limited_dev
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.limited_dev.botendo.util
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
object TimeUtil {
|
||||||
|
fun getTimeFormatedShortend(time: Long): String? {
|
||||||
|
var time = time
|
||||||
|
val days = TimeUnit.MILLISECONDS
|
||||||
|
.toDays(time)
|
||||||
|
time -= TimeUnit.DAYS.toMillis(days)
|
||||||
|
val hours = TimeUnit.MILLISECONDS
|
||||||
|
.toHours(time)
|
||||||
|
time -= TimeUnit.HOURS.toMillis(hours)
|
||||||
|
val minutes = TimeUnit.MILLISECONDS
|
||||||
|
.toMinutes(time)
|
||||||
|
time -= TimeUnit.MINUTES.toMillis(minutes)
|
||||||
|
val seconds = TimeUnit.MILLISECONDS
|
||||||
|
.toSeconds(time)
|
||||||
|
var s = ""
|
||||||
|
if (days >= 1) {
|
||||||
|
s += days.toString() + "d "
|
||||||
|
}
|
||||||
|
if (hours >= 1) {
|
||||||
|
s += hours.toString() + "h "
|
||||||
|
}
|
||||||
|
if (minutes >= 1) {
|
||||||
|
s += minutes.toString() + "m "
|
||||||
|
}
|
||||||
|
if (seconds >= 1 && hours < 1) {
|
||||||
|
s += seconds.toString() + "s"
|
||||||
|
}
|
||||||
|
if (s.isEmpty() || s.isBlank()) {
|
||||||
|
s = "0s"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTimeFormatedRaw(time: Long): String? {
|
||||||
|
var time = time
|
||||||
|
val days = TimeUnit.MILLISECONDS
|
||||||
|
.toDays(time)
|
||||||
|
time -= TimeUnit.DAYS.toMillis(days)
|
||||||
|
val hours = TimeUnit.MILLISECONDS
|
||||||
|
.toHours(time)
|
||||||
|
time -= TimeUnit.HOURS.toMillis(hours)
|
||||||
|
val minutes = TimeUnit.MILLISECONDS
|
||||||
|
.toMinutes(time)
|
||||||
|
time -= TimeUnit.MINUTES.toMillis(minutes)
|
||||||
|
val seconds = TimeUnit.MILLISECONDS
|
||||||
|
.toSeconds(time)
|
||||||
|
var s = ""
|
||||||
|
if (days >= 1) {
|
||||||
|
s += days.toString() + "d "
|
||||||
|
}
|
||||||
|
if (hours >= 1) {
|
||||||
|
s += hours.toString() + "h "
|
||||||
|
}
|
||||||
|
if (minutes >= 1) {
|
||||||
|
s += minutes.toString() + "m "
|
||||||
|
}
|
||||||
|
if (seconds >= 1) {
|
||||||
|
s += seconds.toString() + "s"
|
||||||
|
}
|
||||||
|
if (s.isEmpty() || s.isBlank()) {
|
||||||
|
s = "0s"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue