refactor: Prepare Arguments and stuff
This commit is contained in:
parent
1c20e05066
commit
c901eb2f66
16 changed files with 189 additions and 27 deletions
|
@ -1,6 +1,6 @@
|
|||
package io.github.null2264.tsukumogami.bot.core.module
|
||||
|
||||
import io.github.null2264.tsukumogami.core.module.annotation.Command
|
||||
import io.github.null2264.tsukumogami.core.commands.annotation.Command
|
||||
import io.github.null2264.tsukumogami.core.Context
|
||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.github.null2264.tsukumogami.bot.core.module
|
||||
|
||||
import dev.kord.core.entity.effectiveName
|
||||
import io.github.null2264.tsukumogami.core.module.annotation.Command
|
||||
import io.github.null2264.tsukumogami.core.commands.annotation.Command
|
||||
import io.github.null2264.tsukumogami.core.Context
|
||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||
import kotlinx.datetime.Clock
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package io.github.null2264.tsukumogami.bot.core.module.arguments
|
||||
|
||||
import io.github.null2264.tsukumogami.core.commands.Arguments
|
||||
import io.github.null2264.tsukumogami.core.commands.ext.string
|
||||
|
||||
class TestArguments : Arguments() {
|
||||
val test by string("Test")
|
||||
}
|
|
@ -11,7 +11,8 @@ import dev.kord.gateway.PrivilegedIntent
|
|||
import io.github.null2264.tsukumogami.core.exceptions.CommandException
|
||||
import io.github.null2264.tsukumogami.core.exceptions.CommandNotFound
|
||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||
import io.github.null2264.tsukumogami.core.module.CommandHolder
|
||||
import io.github.null2264.tsukumogami.core.commands.CommandHolder
|
||||
import io.github.null2264.tsukumogami.core.utils.parseCommandAndArguments
|
||||
import kotlin.reflect.full.callSuspend
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
|
@ -22,13 +23,13 @@ abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
|||
private val prefixes: List<String>
|
||||
private val client: Kord
|
||||
|
||||
// TODO: Bind Bot and Kord to Koin
|
||||
init {
|
||||
val currentConfig = BotConfigurator()
|
||||
currentConfig.apply(configurator)
|
||||
|
||||
extensions = mutableMapOf()
|
||||
currentConfig.extensions.forEach {
|
||||
val module = it.call()
|
||||
currentConfig.extensions.forEach { module ->
|
||||
module.setup()
|
||||
module.install(this, currentConfig)
|
||||
extensions[module.name] = module
|
||||
|
@ -59,7 +60,7 @@ abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
|||
fun getCommand(name: String) = commands[name]
|
||||
|
||||
private fun getContext(message: Message): Context {
|
||||
val candidate = message.content.hasPrefix()
|
||||
val candidate = message.content.parsePrefixCommandAndArguments()
|
||||
return Context(this, message, candidate?.first, candidate?.second)
|
||||
}
|
||||
|
||||
|
@ -91,14 +92,16 @@ abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
|||
Logger.i { "Online! ${client.getSelf().username}" }
|
||||
}
|
||||
|
||||
fun String.hasPrefix(): Pair<String, String>? {
|
||||
private fun String.parsePrefixCommandAndArguments(): Pair<String, List<String>>? {
|
||||
if (this.isBlank()) return null
|
||||
|
||||
var ret: Pair<String, String>? = null
|
||||
var ret: Pair<String, List<String>>? = null
|
||||
|
||||
prefixes.forEach {
|
||||
if (this.substring(0, it.length) == it) {
|
||||
ret = Pair(this.substring(0, it.length), this.substring(it.length).split(" ").first())
|
||||
val prefix = this.substring(0, it.length)
|
||||
val cleanPrompt = this.substring(it.length)
|
||||
ret = Pair(prefix, cleanPrompt.parseCommandAndArguments())
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
package io.github.null2264.tsukumogami.core
|
||||
|
||||
import io.github.null2264.tsukumogami.core.module.internal.Modules
|
||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||
import io.github.null2264.tsukumogami.core.module.CommandHolder
|
||||
import kotlin.reflect.KClass
|
||||
import io.github.null2264.tsukumogami.core.commands.CommandHolder
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
class BotConfigurator internal constructor() {
|
||||
|
||||
internal val commands = mutableMapOf<String, CommandHolder>()
|
||||
internal val extensions = mutableListOf<KFunction<BotModule>>()
|
||||
internal val extensions = Modules()
|
||||
internal val prefixes = mutableListOf<String>()
|
||||
var token: String = ""
|
||||
|
||||
|
@ -20,13 +19,7 @@ class BotConfigurator internal constructor() {
|
|||
}
|
||||
|
||||
fun extensions(vararg extensions: KFunction<BotModule>) {
|
||||
extensions.forEach {
|
||||
val kClass = it.returnType.classifier as KClass<*>
|
||||
if (!kClass.isSubclassOf(BotModule::class))
|
||||
return
|
||||
|
||||
this.extensions.add(it)
|
||||
}
|
||||
this.extensions.initializeAndAddAll(extensions.toList())
|
||||
}
|
||||
|
||||
fun prefixes(vararg prefixes: String) {
|
||||
|
|
|
@ -5,10 +5,10 @@ import dev.kord.core.entity.Message
|
|||
import dev.kord.rest.builder.message.AllowedMentionsBuilder
|
||||
import dev.kord.rest.builder.message.allowedMentions
|
||||
|
||||
class Context(private val bot: AbstractBot, private val message: Message, val prefix: String?, private val commandName: String?) {
|
||||
class Context(private val bot: AbstractBot, private val message: Message, val prefix: String?, private val commandAndArguments: List<String>?) {
|
||||
|
||||
val author get() = message.author
|
||||
val command get() = commandName?.let { bot.getCommand(it) }
|
||||
val command get() = commandAndArguments?.get(0)?.let { bot.getCommand(it) }
|
||||
|
||||
suspend fun send(content: String) = message.channel.createMessage(content)
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package io.github.null2264.tsukumogami.core.commands
|
||||
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
||||
|
||||
data class Argument<T : Any?>(
|
||||
val name: String,
|
||||
val converter: Converter<T>,
|
||||
) {
|
||||
init {
|
||||
converter.argumentObj = this
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package io.github.null2264.tsukumogami.core.commands
|
||||
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
||||
|
||||
open class Arguments {
|
||||
val args = mutableListOf<Argument<*>>()
|
||||
|
||||
fun <R : Any> args(
|
||||
name: String,
|
||||
converter: Converter<R>
|
||||
): Converter<R> {
|
||||
args.add(Argument(name, converter))
|
||||
|
||||
return converter
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
package io.github.null2264.tsukumogami.core.module
|
||||
package io.github.null2264.tsukumogami.core.commands
|
||||
|
||||
import kotlin.reflect.KFunction
|
||||
|
||||
/**
|
||||
* Class holding information about a command
|
||||
*/
|
||||
internal data class CommandHolder(
|
||||
data class CommandHolder internal constructor(
|
||||
val name: String,
|
||||
val extension: String,
|
||||
val description: String? = null,
|
|
@ -1,5 +1,4 @@
|
|||
package io.github.null2264.tsukumogami.core.module.annotation
|
||||
|
||||
package io.github.null2264.tsukumogami.core.commands.annotation
|
||||
|
||||
/**
|
||||
* Annotation to tag a function as command
|
|
@ -0,0 +1,17 @@
|
|||
package io.github.null2264.tsukumogami.core.commands.converters
|
||||
|
||||
import io.github.null2264.tsukumogami.core.commands.Argument
|
||||
import io.github.null2264.tsukumogami.core.commands.Arguments
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
abstract class Converter<OutputType: Any?> {
|
||||
lateinit var argumentObj: Argument<OutputType>
|
||||
|
||||
abstract var parsed: OutputType
|
||||
|
||||
abstract suspend fun parse(input: String): OutputType
|
||||
|
||||
operator fun getValue(thisRef: Arguments, property: KProperty<*>): OutputType {
|
||||
return parsed
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package io.github.null2264.tsukumogami.core.commands.converters.impl
|
||||
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
||||
|
||||
class StringConverter : Converter<String>() {
|
||||
override var parsed: String = ""
|
||||
override suspend fun parse(input: String): String {
|
||||
this.parsed = input
|
||||
return input
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package io.github.null2264.tsukumogami.core.commands.ext
|
||||
|
||||
import io.github.null2264.tsukumogami.core.commands.Arguments
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.impl.StringConverter
|
||||
|
||||
fun Arguments.string(name: String) = args(name, StringConverter())
|
|
@ -2,8 +2,9 @@ package io.github.null2264.tsukumogami.core.module
|
|||
|
||||
import co.touchlab.kermit.Logger
|
||||
import io.github.null2264.tsukumogami.core.AbstractBot
|
||||
import io.github.null2264.tsukumogami.core.module.annotation.Command
|
||||
import io.github.null2264.tsukumogami.core.commands.annotation.Command
|
||||
import io.github.null2264.tsukumogami.core.BotConfigurator
|
||||
import io.github.null2264.tsukumogami.core.commands.CommandHolder
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.kotlinFunction
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package io.github.null2264.tsukumogami.core.module.internal
|
||||
|
||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||
import java.util.function.Consumer
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
class Modules {
|
||||
|
||||
private val list = mutableListOf<BotModule>()
|
||||
|
||||
fun get(index: Int) = list[index]
|
||||
|
||||
private fun KFunction<BotModule>.tryInitialize(): BotModule? {
|
||||
val kClass = this.returnType.classifier as KClass<*>
|
||||
if (!kClass.isSubclassOf(BotModule::class))
|
||||
return null
|
||||
|
||||
return this.call()
|
||||
}
|
||||
|
||||
fun initializeAndAddAll(modules: List<KFunction<BotModule>>) {
|
||||
addAll(modules.mapNotNull { it.tryInitialize() })
|
||||
}
|
||||
|
||||
fun addAll(modules: List<BotModule>) {
|
||||
list.addAll(modules)
|
||||
}
|
||||
|
||||
fun add(module: KFunction<BotModule>) {
|
||||
module.tryInitialize()?.let { add(it) }
|
||||
}
|
||||
|
||||
fun add(module: BotModule) {
|
||||
list.add(module)
|
||||
}
|
||||
|
||||
fun forEach(consumer: Consumer<in BotModule>) = list.forEach(consumer)
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package io.github.null2264.tsukumogami.core.utils
|
||||
|
||||
fun String.parseCommandAndArguments(): List<String> {
|
||||
if (isBlank()) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val result = mutableListOf<String>()
|
||||
val currentToken = StringBuilder()
|
||||
var inQuotes = false
|
||||
|
||||
for (char in this) {
|
||||
when (char) {
|
||||
'"' -> {
|
||||
if (inQuotes) {
|
||||
// Closing quote: add the accumulated token
|
||||
result.add(currentToken.toString())
|
||||
currentToken.clear()
|
||||
inQuotes = false
|
||||
} else {
|
||||
// Opening quote:
|
||||
// If there's an existing token (e.g., word"another"), add it first
|
||||
if (currentToken.isNotEmpty()) {
|
||||
result.add(currentToken.toString())
|
||||
currentToken.clear()
|
||||
}
|
||||
inQuotes = true
|
||||
}
|
||||
}
|
||||
' ' -> {
|
||||
if (inQuotes) {
|
||||
// Space inside quotes: append it
|
||||
currentToken.append(char)
|
||||
} else {
|
||||
// Space outside quotes: separator
|
||||
if (currentToken.isNotEmpty()) {
|
||||
result.add(currentToken.toString())
|
||||
currentToken.clear()
|
||||
}
|
||||
// Ignore multiple spaces between tokens
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// Any other character: append it
|
||||
currentToken.append(char)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add any remaining token after the loop (e.g., if the string doesn't end with a quote or space)
|
||||
if (currentToken.isNotEmpty()) {
|
||||
result.add(currentToken.toString())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue