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
|
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.Context
|
||||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.github.null2264.tsukumogami.bot.core.module
|
package io.github.null2264.tsukumogami.bot.core.module
|
||||||
|
|
||||||
import dev.kord.core.entity.effectiveName
|
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.Context
|
||||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||||
import kotlinx.datetime.Clock
|
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.CommandException
|
||||||
import io.github.null2264.tsukumogami.core.exceptions.CommandNotFound
|
import io.github.null2264.tsukumogami.core.exceptions.CommandNotFound
|
||||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
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 kotlin.reflect.full.callSuspend
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
@ -22,13 +23,13 @@ abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
||||||
private val prefixes: List<String>
|
private val prefixes: List<String>
|
||||||
private val client: Kord
|
private val client: Kord
|
||||||
|
|
||||||
|
// TODO: Bind Bot and Kord to Koin
|
||||||
init {
|
init {
|
||||||
val currentConfig = BotConfigurator()
|
val currentConfig = BotConfigurator()
|
||||||
currentConfig.apply(configurator)
|
currentConfig.apply(configurator)
|
||||||
|
|
||||||
extensions = mutableMapOf()
|
extensions = mutableMapOf()
|
||||||
currentConfig.extensions.forEach {
|
currentConfig.extensions.forEach { module ->
|
||||||
val module = it.call()
|
|
||||||
module.setup()
|
module.setup()
|
||||||
module.install(this, currentConfig)
|
module.install(this, currentConfig)
|
||||||
extensions[module.name] = module
|
extensions[module.name] = module
|
||||||
|
@ -59,7 +60,7 @@ abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
||||||
fun getCommand(name: String) = commands[name]
|
fun getCommand(name: String) = commands[name]
|
||||||
|
|
||||||
private fun getContext(message: Message): Context {
|
private fun getContext(message: Message): Context {
|
||||||
val candidate = message.content.hasPrefix()
|
val candidate = message.content.parsePrefixCommandAndArguments()
|
||||||
return Context(this, message, candidate?.first, candidate?.second)
|
return Context(this, message, candidate?.first, candidate?.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,14 +92,16 @@ abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
||||||
Logger.i { "Online! ${client.getSelf().username}" }
|
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
|
if (this.isBlank()) return null
|
||||||
|
|
||||||
var ret: Pair<String, String>? = null
|
var ret: Pair<String, List<String>>? = null
|
||||||
|
|
||||||
prefixes.forEach {
|
prefixes.forEach {
|
||||||
if (this.substring(0, it.length) == it) {
|
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
|
return@forEach
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
package io.github.null2264.tsukumogami.core
|
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.BotModule
|
||||||
import io.github.null2264.tsukumogami.core.module.CommandHolder
|
import io.github.null2264.tsukumogami.core.commands.CommandHolder
|
||||||
import kotlin.reflect.KClass
|
|
||||||
import kotlin.reflect.KFunction
|
import kotlin.reflect.KFunction
|
||||||
import kotlin.reflect.full.isSubclassOf
|
|
||||||
|
|
||||||
class BotConfigurator internal constructor() {
|
class BotConfigurator internal constructor() {
|
||||||
|
|
||||||
internal val commands = mutableMapOf<String, CommandHolder>()
|
internal val commands = mutableMapOf<String, CommandHolder>()
|
||||||
internal val extensions = mutableListOf<KFunction<BotModule>>()
|
internal val extensions = Modules()
|
||||||
internal val prefixes = mutableListOf<String>()
|
internal val prefixes = mutableListOf<String>()
|
||||||
var token: String = ""
|
var token: String = ""
|
||||||
|
|
||||||
|
@ -20,13 +19,7 @@ class BotConfigurator internal constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extensions(vararg extensions: KFunction<BotModule>) {
|
fun extensions(vararg extensions: KFunction<BotModule>) {
|
||||||
extensions.forEach {
|
this.extensions.initializeAndAddAll(extensions.toList())
|
||||||
val kClass = it.returnType.classifier as KClass<*>
|
|
||||||
if (!kClass.isSubclassOf(BotModule::class))
|
|
||||||
return
|
|
||||||
|
|
||||||
this.extensions.add(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun prefixes(vararg prefixes: String) {
|
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.AllowedMentionsBuilder
|
||||||
import dev.kord.rest.builder.message.allowedMentions
|
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 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)
|
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
|
import kotlin.reflect.KFunction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class holding information about a command
|
* Class holding information about a command
|
||||||
*/
|
*/
|
||||||
internal data class CommandHolder(
|
data class CommandHolder internal constructor(
|
||||||
val name: String,
|
val name: String,
|
||||||
val extension: String,
|
val extension: String,
|
||||||
val description: String? = null,
|
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
|
* 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 co.touchlab.kermit.Logger
|
||||||
import io.github.null2264.tsukumogami.core.AbstractBot
|
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.BotConfigurator
|
||||||
|
import io.github.null2264.tsukumogami.core.commands.CommandHolder
|
||||||
import kotlin.reflect.jvm.isAccessible
|
import kotlin.reflect.jvm.isAccessible
|
||||||
import kotlin.reflect.jvm.kotlinFunction
|
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