refactor: Completely changed the API and a working argument
This commit is contained in:
parent
690812b628
commit
411e183e04
19 changed files with 244 additions and 199 deletions
|
@ -2,9 +2,8 @@ package io.github.null2264.tsukumogami.bot
|
||||||
|
|
||||||
import co.touchlab.kermit.Logger
|
import co.touchlab.kermit.Logger
|
||||||
import io.github.null2264.tsukumogami.bot.core.di.appModule
|
import io.github.null2264.tsukumogami.bot.core.di.appModule
|
||||||
import io.github.null2264.tsukumogami.bot.core.module.DeveloperModule
|
import io.github.null2264.tsukumogami.bot.core.module.generalModule
|
||||||
import io.github.null2264.tsukumogami.bot.core.module.GeneralModule
|
import io.github.null2264.tsukumogami.core.bot
|
||||||
import io.github.null2264.tsukumogami.bot.core.Bot
|
|
||||||
import org.koin.core.context.GlobalContext.startKoin
|
import org.koin.core.context.GlobalContext.startKoin
|
||||||
|
|
||||||
suspend fun main() {
|
suspend fun main() {
|
||||||
|
@ -13,13 +12,13 @@ suspend fun main() {
|
||||||
modules(appModule)
|
modules(appModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
Bot {
|
bot {
|
||||||
Logger.setTag("Tsukumogami")
|
Logger.setTag("Tsukumogami")
|
||||||
|
|
||||||
token = System.getenv("DISCORD_TOKEN")
|
token = System.getenv("DISCORD_TOKEN")
|
||||||
|
|
||||||
prefixes("src!", "mm!") // mm! for backwards compatibility
|
prefixes("src!", "mm!") // mm! for backwards compatibility
|
||||||
|
|
||||||
extensions(::DeveloperModule, ::GeneralModule)
|
modules(generalModule)
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package io.github.null2264.tsukumogami.bot.core
|
|
||||||
|
|
||||||
import io.github.null2264.tsukumogami.core.AbstractBot
|
|
||||||
import io.github.null2264.tsukumogami.core.BotConfigurator
|
|
||||||
|
|
||||||
class Bot(block: BotConfigurator.() -> Unit = {}) : AbstractBot(block)
|
|
|
@ -1,17 +1,13 @@
|
||||||
package io.github.null2264.tsukumogami.bot.core.module
|
package io.github.null2264.tsukumogami.bot.core.module
|
||||||
|
|
||||||
import io.github.null2264.tsukumogami.core.commands.annotation.Command
|
//class DeveloperModule : BotModule("Developer", "Only for developers") {
|
||||||
import io.github.null2264.tsukumogami.core.Context
|
//
|
||||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
// @Command(
|
||||||
|
// name="poweroff",
|
||||||
class DeveloperModule : BotModule("Developer", "Only for developers") {
|
// description="Turn the bot off",
|
||||||
|
// )
|
||||||
@Command(
|
// private suspend fun shutdown(ctx: Context) {
|
||||||
name="poweroff",
|
// ctx.reply("Shutting Down...", mentionsAuthor = true)
|
||||||
description="Turn the bot off",
|
// bot?.stop()
|
||||||
)
|
// }
|
||||||
private suspend fun shutdown(ctx: Context) {
|
//}
|
||||||
ctx.reply("Shutting Down...", mentionsAuthor = true)
|
|
||||||
bot?.stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
package io.github.null2264.tsukumogami.bot.core.module
|
package io.github.null2264.tsukumogami.bot.core.module
|
||||||
|
|
||||||
import dev.kord.core.entity.effectiveName
|
import io.github.null2264.tsukumogami.bot.core.module.arguments.TestArguments
|
||||||
import io.github.null2264.tsukumogami.core.commands.annotation.Command
|
import io.github.null2264.tsukumogami.core.module.api.botModules
|
||||||
import io.github.null2264.tsukumogami.core.Context
|
|
||||||
import io.github.null2264.tsukumogami.core.module.BotModule
|
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
|
|
||||||
class GeneralModule : BotModule("General", "idk") {
|
val generalModule = botModules("General") {
|
||||||
|
commands("ping", description = "Ping the bot!") { ctx ->
|
||||||
@Command(description = "Ping the bot!")
|
|
||||||
private suspend fun ping(ctx: Context) {
|
|
||||||
val startTime = Clock.System.now()
|
val startTime = Clock.System.now()
|
||||||
ctx.typing()
|
ctx.typing()
|
||||||
val endTime = Clock.System.now()
|
val endTime = Clock.System.now()
|
||||||
ctx.send("Pong! ${endTime.toEpochMilliseconds() - startTime.toEpochMilliseconds()}ms")
|
ctx.send("Pong! ${endTime.toEpochMilliseconds() - startTime.toEpochMilliseconds()}ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command("test")
|
groups("group") {
|
||||||
private suspend fun differentName(ctx: Context) {
|
commands("test", arguments = ::TestArguments) { ctx, args -> ctx.send("Hello world ${args.test}") }
|
||||||
ctx.send("Hello World! ${ctx.author?.effectiveName}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commands("test", arguments = ::TestArguments) { ctx, args -> ctx.send("Hello world ${args.test}") }
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,45 +8,52 @@ import dev.kord.core.event.message.MessageCreateEvent
|
||||||
import dev.kord.core.on
|
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 io.github.null2264.tsukumogami.core.commands.Command
|
||||||
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.commands.CommandHolder
|
import io.github.null2264.tsukumogami.core.commands.IGroup
|
||||||
import io.github.null2264.tsukumogami.core.utils.parseCommandAndArguments
|
import io.github.null2264.tsukumogami.core.ext.parseCommandAndArguments
|
||||||
import kotlin.reflect.full.callSuspend
|
import kotlin.reflect.full.callSuspend
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
open class Bot internal constructor(): IGroup {
|
||||||
|
|
||||||
private val commands: Map<String, CommandHolder>
|
lateinit var client: Kord
|
||||||
private val extensions: Map<String, BotModule>
|
private val modules = mutableMapOf<String, BotModule>()
|
||||||
private val prefixes: List<String>
|
private val _prefixes = mutableListOf<String>()
|
||||||
private val client: Kord
|
val prefixes: List<String> get() = _prefixes.toList()
|
||||||
|
internal lateinit var token: String
|
||||||
|
override val allCommands: MutableMap<String, Command> = mutableMapOf()
|
||||||
|
|
||||||
// TODO: Bind Bot and Kord to Koin
|
fun addModule(module: BotModule) {
|
||||||
init {
|
modules[module.name] = module.install(this)
|
||||||
val currentConfig = BotConfigurator()
|
}
|
||||||
currentConfig.apply(configurator)
|
|
||||||
|
|
||||||
extensions = mutableMapOf()
|
fun addPrefix(prefix: String) {
|
||||||
currentConfig.extensions.forEach { module ->
|
_prefixes.add(prefix)
|
||||||
module.setup()
|
}
|
||||||
module.install(this, currentConfig)
|
|
||||||
extensions[module.name] = module
|
fun addCommand(command: Command) {
|
||||||
|
if (allCommands.containsKey(command.name)) {
|
||||||
|
throw IllegalStateException("Duplicate command: '${command.name}'")
|
||||||
}
|
}
|
||||||
commands = currentConfig.commands
|
allCommands[command.name] = command
|
||||||
prefixes = currentConfig.prefixes
|
}
|
||||||
|
|
||||||
client = runBlocking {
|
fun removeCommand(command: Command) {
|
||||||
Kord(currentConfig.token).apply {
|
if (!allCommands.containsKey(command.name)) {
|
||||||
on<ReadyEvent> { onReady() }
|
throw IllegalStateException("Command not found: '${command.name}'")
|
||||||
|
|
||||||
on<MessageCreateEvent> { onMessage(this.message, this) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
allCommands.remove(command.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
open suspend fun start() {
|
open suspend fun start() {
|
||||||
|
client = Kord(token).apply {
|
||||||
|
on<ReadyEvent> { onReady() }
|
||||||
|
on<MessageCreateEvent> { onMessage(this.message, this) }
|
||||||
|
}
|
||||||
|
|
||||||
client.login {
|
client.login {
|
||||||
@OptIn(PrivilegedIntent::class)
|
@OptIn(PrivilegedIntent::class)
|
||||||
intents += Intent.MessageContent
|
intents += Intent.MessageContent
|
||||||
|
@ -57,11 +64,13 @@ abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
||||||
client.shutdown()
|
client.shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCommand(name: String) = commands[name]
|
fun getCommand(name: String?) = allCommands[name]
|
||||||
|
|
||||||
private fun getContext(message: Message): Context {
|
private fun getContext(message: Message): Context {
|
||||||
val candidate = message.content.parsePrefixCommandAndArguments()
|
val candidate = message.content.parsePrefixCommandAndArguments()
|
||||||
return Context(this, message, candidate?.first, candidate?.second)
|
val context = Context(this, message, candidate?.first, candidate?.second)
|
||||||
|
context.command = getCommand(candidate?.second?.get(0))
|
||||||
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
open suspend fun onCommandError(context: Context, error: CommandException) {
|
open suspend fun onCommandError(context: Context, error: CommandException) {
|
||||||
|
@ -72,9 +81,7 @@ abstract class AbstractBot(configurator: BotConfigurator.() -> Unit) {
|
||||||
val ctx = getContext(message)
|
val ctx = getContext(message)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ctx.command?.let {
|
ctx.command?.invoke(ctx) ?: throw CommandNotFound()
|
||||||
it.callback.callSuspend(extensions[it.extension], ctx)
|
|
||||||
} ?: throw CommandNotFound()
|
|
||||||
} catch (e: CommandException) {
|
} catch (e: CommandException) {
|
||||||
onCommandError(ctx, e)
|
onCommandError(ctx, e)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
|
@ -1,32 +0,0 @@
|
||||||
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.commands.CommandHolder
|
|
||||||
import kotlin.reflect.KFunction
|
|
||||||
|
|
||||||
class BotConfigurator internal constructor() {
|
|
||||||
|
|
||||||
internal val commands = mutableMapOf<String, CommandHolder>()
|
|
||||||
internal val extensions = Modules()
|
|
||||||
internal val prefixes = mutableListOf<String>()
|
|
||||||
var token: String = ""
|
|
||||||
|
|
||||||
internal fun isExists(name: String?) = this.commands.containsKey(name)
|
|
||||||
|
|
||||||
internal fun commands(command: CommandHolder, name: String? = null) {
|
|
||||||
this.commands[if (name.isNullOrEmpty()) command.name else name] = command
|
|
||||||
}
|
|
||||||
|
|
||||||
fun extensions(vararg extensions: KFunction<BotModule>) {
|
|
||||||
this.extensions.initializeAndAddAll(extensions.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun prefixes(vararg prefixes: String) {
|
|
||||||
prefixes(prefixes.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun prefixes(prefixes: List<String>) {
|
|
||||||
this.prefixes.addAll(prefixes)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package io.github.null2264.tsukumogami.core
|
||||||
|
|
||||||
|
import dev.kord.core.Kord
|
||||||
|
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||||
|
import kotlin.reflect.KFunction
|
||||||
|
|
||||||
|
class BotHolder internal constructor(
|
||||||
|
val bot: Bot
|
||||||
|
) {
|
||||||
|
|
||||||
|
internal val prefixes = mutableListOf<String>()
|
||||||
|
var token: String
|
||||||
|
get() = bot.token
|
||||||
|
set(value) {
|
||||||
|
bot.token = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun modules(vararg modules: BotModule) {
|
||||||
|
modules.forEach(bot::addModule)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun prefixes(vararg prefixes: String) {
|
||||||
|
prefixes.forEach(bot::addPrefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bot(clazz: KFunction<Bot> = ::Bot, declaration: BotHolder.() -> Unit): Bot {
|
||||||
|
val bot = clazz.call()
|
||||||
|
val holder = BotHolder(bot)
|
||||||
|
declaration(holder)
|
||||||
|
return holder.bot
|
||||||
|
}
|
|
@ -4,18 +4,26 @@ import dev.kord.core.behavior.channel.createMessage
|
||||||
import dev.kord.core.entity.Message
|
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
|
||||||
import io.github.null2264.tsukumogami.core.commands.CommandHolder
|
import io.github.null2264.tsukumogami.core.commands.Command
|
||||||
|
|
||||||
class Context(
|
class Context(
|
||||||
private val bot: AbstractBot,
|
private val bot: Bot,
|
||||||
private val message: Message,
|
private val message: Message,
|
||||||
|
/**
|
||||||
|
* The prefix that used to invoke the command
|
||||||
|
*/
|
||||||
val prefix: String?,
|
val prefix: String?,
|
||||||
commandAndArguments: List<String>?,
|
/**
|
||||||
|
* Potential command name and/or arguments
|
||||||
|
*/
|
||||||
|
val candidate: List<String>?,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val author get() = message.author
|
val author get() = message.author
|
||||||
val commandAndArguments: MutableList<String>? = commandAndArguments?.toMutableList()
|
|
||||||
val command: CommandHolder? = this.commandAndArguments?.removeAt(0)?.let { bot.getCommand(it) }
|
/**
|
||||||
|
* The command that currently being invoked
|
||||||
|
*/
|
||||||
|
var command: Command? = null
|
||||||
|
|
||||||
suspend fun send(content: String) = message.channel.createMessage(content)
|
suspend fun send(content: String) = message.channel.createMessage(content)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package io.github.null2264.tsukumogami.core.annotation
|
||||||
|
|
||||||
|
@RequiresOptIn(message = "Intended for internal usage. External usage is strongly discouraged.", level = RequiresOptIn.Level.ERROR)
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@Target(
|
||||||
|
AnnotationTarget.CLASS,
|
||||||
|
AnnotationTarget.TYPEALIAS,
|
||||||
|
AnnotationTarget.FUNCTION,
|
||||||
|
AnnotationTarget.PROPERTY,
|
||||||
|
AnnotationTarget.FIELD,
|
||||||
|
AnnotationTarget.CONSTRUCTOR,
|
||||||
|
)
|
||||||
|
annotation class TsukumogamiInternalApi
|
|
@ -2,7 +2,7 @@ package io.github.null2264.tsukumogami.core.commands
|
||||||
|
|
||||||
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
import io.github.null2264.tsukumogami.core.commands.converters.Converter
|
||||||
|
|
||||||
open class Arguments {
|
abstract class Arguments {
|
||||||
val args = mutableListOf<Argument<*>>()
|
val args = mutableListOf<Argument<*>>()
|
||||||
|
|
||||||
fun <R : Any> args(
|
fun <R : Any> args(
|
||||||
|
@ -13,4 +13,10 @@ open class Arguments {
|
||||||
|
|
||||||
return converter
|
return converter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun parse(value: String) {
|
||||||
|
args.forEach { arg ->
|
||||||
|
arg.converter.parse(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package io.github.null2264.tsukumogami.core.commands
|
||||||
|
|
||||||
|
import io.github.null2264.tsukumogami.core.Context
|
||||||
|
import kotlin.reflect.KFunction
|
||||||
|
|
||||||
|
open class Command(
|
||||||
|
val name: String,
|
||||||
|
val alias: Set<String>,
|
||||||
|
val description: String,
|
||||||
|
private val arguments: KFunction<Arguments>,
|
||||||
|
private val handler: suspend (Context, Arguments) -> Unit,
|
||||||
|
) {
|
||||||
|
|
||||||
|
open suspend fun invoke(context: Context) {
|
||||||
|
val parsedArguments = arguments.call()
|
||||||
|
// TODO: Don't hardcode this
|
||||||
|
parsedArguments.parse(context.candidate?.get(1) ?: "test")
|
||||||
|
handler.invoke(context, parsedArguments)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
package io.github.null2264.tsukumogami.core.commands
|
|
||||||
|
|
||||||
import kotlin.reflect.KFunction
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class holding information about a command
|
|
||||||
*/
|
|
||||||
data class CommandHolder internal constructor(
|
|
||||||
val name: String,
|
|
||||||
val extension: String,
|
|
||||||
val description: String? = null,
|
|
||||||
val callback: KFunction<*>,
|
|
||||||
)
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
package io.github.null2264.tsukumogami.core.commands
|
||||||
|
|
||||||
|
class EmptyArguments : Arguments() {
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package io.github.null2264.tsukumogami.core.commands
|
||||||
|
|
||||||
|
import io.github.null2264.tsukumogami.core.Context
|
||||||
|
|
||||||
|
class Group(
|
||||||
|
name: String,
|
||||||
|
alias: Set<String>,
|
||||||
|
description: String,
|
||||||
|
) :
|
||||||
|
IGroup,
|
||||||
|
Command(
|
||||||
|
name,
|
||||||
|
alias,
|
||||||
|
description,
|
||||||
|
::EmptyArguments,
|
||||||
|
{ _, _ -> /* No handler for group to match the behaviour of Discord's slash command */ },
|
||||||
|
) {
|
||||||
|
|
||||||
|
override val allCommands: MutableMap<String, Command> = mutableMapOf()
|
||||||
|
|
||||||
|
override suspend fun invoke(context: Context) {
|
||||||
|
val command = allCommands["TODO"] ?: return
|
||||||
|
context.command = command
|
||||||
|
command.invoke(context)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package io.github.null2264.tsukumogami.core.commands
|
||||||
|
|
||||||
|
import io.github.null2264.tsukumogami.core.Context
|
||||||
|
import kotlin.reflect.KFunction
|
||||||
|
|
||||||
|
interface IGroup {
|
||||||
|
|
||||||
|
val allCommands: MutableMap<String, Command>
|
||||||
|
|
||||||
|
private fun addCommand(command: Command) {
|
||||||
|
allCommands[command.name] = command
|
||||||
|
command.alias.forEach { allCommands[it] = command }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun commands(
|
||||||
|
name: String,
|
||||||
|
alias: Set<String> = setOf(),
|
||||||
|
description: String = "",
|
||||||
|
handler: suspend (Context) -> Unit,
|
||||||
|
) {
|
||||||
|
val command = Command(name, alias, description, ::EmptyArguments) { ctx, _ -> handler(ctx) }
|
||||||
|
addCommand(command)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Args : Arguments> commands(
|
||||||
|
name: String,
|
||||||
|
alias: Set<String> = setOf(),
|
||||||
|
description: String = "",
|
||||||
|
arguments: KFunction<Args>,
|
||||||
|
handler: suspend (Context, Args) -> Unit,
|
||||||
|
) {
|
||||||
|
val command = Command(name, alias, description, arguments) { ctx, args -> handler(ctx, args as Args) }
|
||||||
|
addCommand(command)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun groups(
|
||||||
|
name: String,
|
||||||
|
alias: Set<String> = setOf(),
|
||||||
|
description: String = "",
|
||||||
|
declaration: IGroup.() -> Unit,
|
||||||
|
) {
|
||||||
|
val group = Group(name, alias, description)
|
||||||
|
addCommand(group)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package io.github.null2264.tsukumogami.core.utils
|
package io.github.null2264.tsukumogami.core.ext
|
||||||
|
|
||||||
fun String.parseCommandAndArguments(): List<String> {
|
fun String.parseCommandAndArguments(): List<String> {
|
||||||
if (isBlank()) {
|
if (isBlank()) {
|
|
@ -1,48 +1,20 @@
|
||||||
package io.github.null2264.tsukumogami.core.module
|
package io.github.null2264.tsukumogami.core.module
|
||||||
|
|
||||||
import co.touchlab.kermit.Logger
|
import io.github.null2264.tsukumogami.core.Bot
|
||||||
import io.github.null2264.tsukumogami.core.AbstractBot
|
import io.github.null2264.tsukumogami.core.commands.Command
|
||||||
import io.github.null2264.tsukumogami.core.commands.annotation.Command
|
import io.github.null2264.tsukumogami.core.commands.IGroup
|
||||||
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
|
|
||||||
|
|
||||||
abstract class BotModule(val name: String, val description: String? = null) {
|
class BotModule internal constructor(val name: String) : IGroup {
|
||||||
|
|
||||||
var bot: AbstractBot? = null
|
override val allCommands: MutableMap<String, Command> = mutableMapOf()
|
||||||
internal set
|
|
||||||
|
|
||||||
open fun setup() {}
|
internal fun install(bot: Bot): BotModule {
|
||||||
|
allCommands.values.forEach(bot::addCommand)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
internal fun install(bot: AbstractBot, configurator: BotConfigurator) {
|
internal fun uninstall(bot: Bot): BotModule {
|
||||||
this.bot = bot
|
allCommands.values.forEach(bot::removeCommand)
|
||||||
|
return this
|
||||||
val methods = this::class.java.declaredMethods
|
|
||||||
for (method in methods) {
|
|
||||||
for (annotation in method.annotations) {
|
|
||||||
if (annotation !is Command)
|
|
||||||
continue
|
|
||||||
|
|
||||||
configurator.apply {
|
|
||||||
val kMethod = method.kotlinFunction
|
|
||||||
if (isExists(kMethod?.name)) {
|
|
||||||
Logger.e { "Command already exists" }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
kMethod?.let {
|
|
||||||
it.isAccessible = true
|
|
||||||
commands(
|
|
||||||
CommandHolder(
|
|
||||||
annotation.name.ifEmpty { it.name },
|
|
||||||
name,
|
|
||||||
annotation.description.ifEmpty { description },
|
|
||||||
it,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.github.null2264.tsukumogami.core.module.api
|
||||||
|
|
||||||
|
import io.github.null2264.tsukumogami.core.module.BotModule
|
||||||
|
|
||||||
|
typealias BotModuleDeclaration = BotModule.() -> Unit
|
||||||
|
|
||||||
|
fun botModules(name: String, declaration: BotModuleDeclaration): BotModule {
|
||||||
|
val module = BotModule(name)
|
||||||
|
declaration(module)
|
||||||
|
return module
|
||||||
|
}
|
|
@ -1,40 +0,0 @@
|
||||||
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)
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue