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
|
||||
|
||||
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.TokenManager
|
||||
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.PrivilegedIntent
|
||||
import dev.kord.rest.builder.interaction.boolean
|
||||
import dev.kord.rest.builder.interaction.integer
|
||||
import dev.kord.rest.builder.interaction.string
|
||||
|
||||
object Bot {
|
||||
//The kord object gets set at app launch
|
||||
var kord: Kord? = null
|
||||
suspend fun start() {
|
||||
Logger.out("Starting Bot...")
|
||||
|
||||
//Load config
|
||||
TokenManager.load()
|
||||
|
||||
|
||||
//Don't run the bot when there is no bot token in config
|
||||
if (TokenManager.token == "empty") {
|
||||
Logger.out("The config does not contain a bot token")
|
||||
return
|
||||
}
|
||||
|
||||
// start the bot
|
||||
//Register slash commands to bot & Discord
|
||||
SlashCommandManager.register()
|
||||
|
||||
//Add Bot token to kord
|
||||
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 {
|
||||
// Load gateway privileges
|
||||
@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 {
|
||||
|
||||
val commands = mutableListOf<SlashCommand>()
|
||||
|
||||
fun register() {
|
||||
|
||||
}
|
||||
|
||||
fun registerAtDiscord(commands: List<SlashCommand>) {
|
||||
//Bot.kord.createGlobalApplicationCommands {
|
||||
|
||||
//}
|
||||
commands.add(InfoCommand())
|
||||
}
|
||||
}
|
|
@ -17,10 +17,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
package de.limited_dev.botendo.commands.slash
|
||||
|
||||
abstract class SlashCommand(val name: String, val description: String, val options: Array<String>? = null) {
|
||||
|
||||
fun onSlashCommand() {}
|
||||
package de.limited_dev.botendo.commands.slash.component.options
|
||||
|
||||
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
|
||||
|
||||
object SlashCommandListener {
|
||||
|
||||
fun check() {
|
||||
package de.limited_dev.botendo.commands.slash.component.options
|
||||
|
||||
}
|
||||
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