feat: Improve arguments
* Add UserConverter * Add a way to specify default value
This commit is contained in:
parent
fce8afa2b2
commit
04472f8bfa
13 changed files with 119 additions and 21 deletions
|
@ -1,5 +1,6 @@
|
|||
package io.github.null2264.tsukumogami.bot.core.module
|
||||
|
||||
import io.github.null2264.tsukumogami.bot.core.module.arguments.Test2Arguments
|
||||
import io.github.null2264.tsukumogami.bot.core.module.arguments.TestArguments
|
||||
import io.github.null2264.tsukumogami.core.module.api.botModules
|
||||
import kotlinx.datetime.Clock
|
||||
|
@ -13,7 +14,7 @@ val generalModule = botModules("General") {
|
|||
}
|
||||
|
||||
groups("group") {
|
||||
commands("test", arguments = ::TestArguments) { ctx, args -> ctx.send("Hello world ${args.test}") }
|
||||
commands("test", arguments = ::Test2Arguments) { ctx, args -> ctx.send("Hello world ${args.user}") }
|
||||
}
|
||||
|
||||
commands("test", arguments = ::TestArguments) { ctx, args -> ctx.send("Hello world ${args.test}") }
|
||||
|
|
|
@ -2,7 +2,14 @@ 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
|
||||
import io.github.null2264.tsukumogami.core.commands.ext.user
|
||||
|
||||
class TestArguments : Arguments() {
|
||||
val test by string("Test")
|
||||
val test by string("Test") {
|
||||
default("Lmao")
|
||||
}
|
||||
}
|
||||
|
||||
class Test2Arguments : Arguments() {
|
||||
val user by user("User")
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ open class Bot internal constructor(): IGroup {
|
|||
private fun getContext(message: Message): Context {
|
||||
val candidate = message.content.parsePrefixCommandAndArguments()
|
||||
val context = Context(this, message, candidate?.first, candidate?.second?.toMutableList())
|
||||
context.command = getCommand(context.candidate?.removeAt(0))
|
||||
context.command = getCommand(context.pullCandidateOrNull())
|
||||
return context
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import dev.kord.rest.builder.message.allowedMentions
|
|||
import io.github.null2264.tsukumogami.core.commands.Command
|
||||
|
||||
class Context(
|
||||
private val bot: Bot,
|
||||
val bot: Bot,
|
||||
private val message: Message,
|
||||
/**
|
||||
* The prefix that used to invoke the command
|
||||
|
@ -19,6 +19,9 @@ class Context(
|
|||
val candidate: MutableList<String>?,
|
||||
) {
|
||||
|
||||
/**
|
||||
* The user that invoked the command
|
||||
*/
|
||||
val author get() = message.author
|
||||
|
||||
/**
|
||||
|
@ -26,6 +29,13 @@ class Context(
|
|||
*/
|
||||
var command: Command? = null
|
||||
|
||||
fun getCandidateOrNull() = candidate?.getOrNull(0)
|
||||
fun pullCandidateOrNull() = candidate?.removeFirstOrNull()
|
||||
fun pullCandidateIf(predicate: () -> Boolean): String? {
|
||||
if (predicate()) return candidate?.removeFirstOrNull()
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun send(content: String) = message.channel.createMessage(content)
|
||||
|
||||
suspend fun reply(content: String, mentionsAuthor: Boolean = false) = message.channel.createMessage {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.github.null2264.tsukumogami.core.commands
|
||||
|
||||
import io.github.null2264.tsukumogami.core.Context
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
||||
|
||||
abstract class Arguments {
|
||||
|
@ -15,17 +16,13 @@ abstract class Arguments {
|
|||
return converter
|
||||
}
|
||||
|
||||
suspend fun parse(values: List<String>?) {
|
||||
val currentValues = values?.toMutableList()
|
||||
suspend fun parse(context: Context) {
|
||||
val currentValues = context.candidate?.toMutableList()
|
||||
|
||||
run {
|
||||
args.forEach { arg ->
|
||||
val value = try {
|
||||
currentValues?.removeAt(0)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
} ?: return@run
|
||||
arg.converter.parse(value)
|
||||
val value = currentValues?.removeFirstOrNull() ?: return@run
|
||||
arg.converter.parse(context, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ open class Command(
|
|||
|
||||
open suspend fun invoke(context: Context) {
|
||||
val parsedArguments = arguments.call()
|
||||
parsedArguments.parse(context.candidate)
|
||||
parsedArguments.parse(context)
|
||||
handler.invoke(context, parsedArguments)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@ class Group(
|
|||
override val allCommands: MutableMap<String, Command> = mutableMapOf()
|
||||
|
||||
override suspend fun invoke(context: Context) {
|
||||
val command = allCommands[context.candidate?.get(0)] ?: return
|
||||
context.candidate?.removeAt(0)
|
||||
context.command = command
|
||||
val command = allCommands[context.getCandidateOrNull()]
|
||||
context.pullCandidateIf { command != null } ?: return
|
||||
context.command = command!!
|
||||
command.invoke(context)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.github.null2264.tsukumogami.core.commands.converters
|
||||
|
||||
import io.github.null2264.tsukumogami.core.Context
|
||||
import io.github.null2264.tsukumogami.core.commands.Argument
|
||||
import io.github.null2264.tsukumogami.core.commands.Arguments
|
||||
import kotlin.reflect.KProperty
|
||||
|
@ -10,9 +11,14 @@ abstract class Converter<OutputType: Any?> {
|
|||
|
||||
abstract var parsed: OutputType
|
||||
|
||||
abstract suspend fun parse(input: String): OutputType
|
||||
abstract suspend fun parse(context: Context, input: String): OutputType
|
||||
|
||||
operator fun getValue(thisRef: Arguments, property: KProperty<*>): OutputType {
|
||||
return parsed
|
||||
return this.parsed
|
||||
}
|
||||
|
||||
fun default(defaultValue: OutputType): OutputType {
|
||||
this.parsed = defaultValue
|
||||
return this.parsed
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package io.github.null2264.tsukumogami.core.commands.converters.impl
|
||||
|
||||
import io.github.null2264.tsukumogami.core.Context
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
||||
|
||||
class StringConverter : Converter<String>() {
|
||||
|
||||
override var parsed: String = ""
|
||||
|
||||
override suspend fun parse(input: String): String {
|
||||
override suspend fun parse(context: Context, input: String): String {
|
||||
this.parsed = input
|
||||
return input
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package io.github.null2264.tsukumogami.core.commands.converters.impl
|
||||
|
||||
import dev.kord.common.entity.Snowflake
|
||||
import dev.kord.core.entity.User
|
||||
import io.github.null2264.tsukumogami.core.Context
|
||||
import io.github.null2264.tsukumogami.core.annotation.TsukumogamiInternalApi
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
||||
import io.github.null2264.tsukumogami.core.exceptions.CommandException
|
||||
import io.github.null2264.tsukumogami.core.ext.users
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
||||
class UserConverter : Converter<User>() {
|
||||
|
||||
override lateinit var parsed: User
|
||||
|
||||
override suspend fun parse(context: Context, input: String): User {
|
||||
if (input.equals("me", true)) {
|
||||
val user = context.author
|
||||
if (user != null) {
|
||||
this.parsed = user
|
||||
return this.parsed
|
||||
}
|
||||
}
|
||||
if (input.equals("you", true)) {
|
||||
this.parsed = context.bot.client.getSelf()
|
||||
return this.parsed
|
||||
}
|
||||
|
||||
this.parsed = context.findUser(input) ?:
|
||||
throw CommandException("User not found")
|
||||
|
||||
return this.parsed
|
||||
}
|
||||
|
||||
private suspend fun Context.findUser(arg: String): User? =
|
||||
if (arg.startsWith("<@") && arg.endsWith(">")) {
|
||||
val id: String = arg.substring(2, arg.length - 1).replace("!", "")
|
||||
|
||||
try {
|
||||
bot.client.getUser(Snowflake(id))
|
||||
} catch (_: NumberFormatException) {
|
||||
throw CommandException("Invalid user ID")
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
bot.client.getUser(Snowflake(arg))
|
||||
} catch (_: NumberFormatException) {
|
||||
if (!arg.contains("#")) {
|
||||
null
|
||||
} else {
|
||||
bot.client.users.firstOrNull { user ->
|
||||
user.tag.equals(arg, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,19 @@
|
|||
package io.github.null2264.tsukumogami.core.commands.ext
|
||||
|
||||
import dev.kord.core.entity.User
|
||||
import io.github.null2264.tsukumogami.core.commands.Arguments
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.impl.StringConverter
|
||||
import io.github.null2264.tsukumogami.core.commands.converters.impl.UserConverter
|
||||
|
||||
fun Arguments.string(name: String) = args(name, StringConverter())
|
||||
fun Arguments.string(name: String, declaration: Converter<String>.() -> Unit = {}): Converter<String> {
|
||||
val converter = StringConverter()
|
||||
declaration(converter)
|
||||
return args(name, converter)
|
||||
}
|
||||
|
||||
fun Arguments.user(name: String, declaration: Converter<User>.() -> Unit = {}): Converter<User> {
|
||||
val converter = UserConverter()
|
||||
declaration(converter)
|
||||
return args(name, converter)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package io.github.null2264.tsukumogami.core.ext
|
||||
|
||||
import dev.kord.core.Kord
|
||||
import dev.kord.core.supplier.EntitySupplyStrategy
|
||||
|
||||
val Kord.users get() = with(EntitySupplyStrategy.cache).users
|
|
@ -4,7 +4,7 @@ import io.github.null2264.tsukumogami.core.Bot
|
|||
import io.github.null2264.tsukumogami.core.commands.Command
|
||||
import io.github.null2264.tsukumogami.core.commands.IGroup
|
||||
|
||||
class BotModule internal constructor(val name: String) : IGroup {
|
||||
open class BotModule constructor(val name: String) : IGroup {
|
||||
|
||||
override val allCommands: MutableMap<String, Command> = mutableMapOf()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue