mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +08:00
Add allRegisteredCommands;
Add val MiraiConsole.job; Implement command listening; Add simple built-in commands
This commit is contained in:
parent
108e425082
commit
2fd7c6aec7
@ -17,7 +17,10 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.io.charsets.Charset
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.MiraiConsole.INSTANCE
|
||||
import net.mamoe.mirai.console.command.BuiltInCommands
|
||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||
import net.mamoe.mirai.console.command.internal.InternalCommandManager
|
||||
import net.mamoe.mirai.console.command.primaryName
|
||||
import net.mamoe.mirai.console.plugin.PluginLoader
|
||||
import net.mamoe.mirai.console.plugin.PluginManager
|
||||
import net.mamoe.mirai.console.plugin.center.CuiPluginCenter
|
||||
@ -75,6 +78,11 @@ interface MiraiConsole : CoroutineScope {
|
||||
companion object INSTANCE : MiraiConsole by MiraiConsoleInternal
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 [MiraiConsole] 的 [Job]
|
||||
*/
|
||||
val MiraiConsole.job: Job
|
||||
get() = this.coroutineContext[Job] ?: error("Internal error: Job not found in MiraiConsole.coroutineContext")
|
||||
|
||||
//// internal
|
||||
|
||||
@ -132,10 +140,14 @@ internal object MiraiConsoleInternal : CoroutineScope, IMiraiConsole, MiraiConso
|
||||
if (coroutineContext[Job] == null) {
|
||||
throw IllegalMiraiConsoleImplementationError("The coroutineContext given to MiraiConsole must have a Job in it.")
|
||||
}
|
||||
this.coroutineContext[Job]!!.invokeOnCompletion {
|
||||
job.invokeOnCompletion {
|
||||
Bot.botInstances.forEach { kotlin.runCatching { it.close() }.exceptionOrNull()?.let(mainLogger::error) }
|
||||
}
|
||||
|
||||
BuiltInCommands.registerAll()
|
||||
mainLogger.info { "Preparing built-in commands: ${BuiltInCommands.all.joinToString { it.primaryName }}" }
|
||||
InternalCommandManager.commandListener // start
|
||||
|
||||
mainLogger.info { "Loading plugins..." }
|
||||
PluginManager.loadEnablePlugins()
|
||||
mainLogger.info { "${PluginManager.plugins.size} plugin(s) loaded." }
|
||||
|
@ -9,12 +9,114 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.alsoLogin
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.job
|
||||
import net.mamoe.mirai.console.stacktraceString
|
||||
import net.mamoe.mirai.event.selectMessagesUnit
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
/**
|
||||
* 添加一个 [Bot] 实例到全局 Bot 列表, 但不登录.
|
||||
*/
|
||||
fun MiraiConsole.addBot(id: Long, password: String): Bot {
|
||||
return Bot(id, password) {
|
||||
fileBasedDeviceInfo()
|
||||
this.loginSolver = this@addBot.frontEnd.createLoginSolver()
|
||||
redirectNetworkLogToDirectory()
|
||||
redirectBotLogToDirectory()
|
||||
}
|
||||
}
|
||||
|
||||
interface BuiltInCommand : Command
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
object BuiltInCommands
|
||||
|
||||
@Suppress("unused")
|
||||
object BuiltInCommands {
|
||||
|
||||
val all: Array<out Command> by lazy {
|
||||
this::class.nestedClasses.mapNotNull { it.objectInstance as? Command }.toTypedArray()
|
||||
}
|
||||
|
||||
internal fun registerAll() {
|
||||
BuiltInCommands::class.nestedClasses.forEach {
|
||||
(it.objectInstance as? Command)?.register()
|
||||
}
|
||||
}
|
||||
|
||||
object Help : SimpleCommand(
|
||||
ConsoleCommandOwner, "help", "?",
|
||||
description = "Gets help about the console."
|
||||
) {
|
||||
init {
|
||||
Runtime.getRuntime().addShutdownHook(thread(false) {
|
||||
runBlocking { Stop.execute(ConsoleCommandSender.instance) }
|
||||
})
|
||||
}
|
||||
|
||||
@Handler
|
||||
suspend fun CommandSender.handle() {
|
||||
sendMessage("现在有指令: ${allRegisteredCommands.joinToString { it.primaryName }}")
|
||||
sendMessage("帮助还没写, 将就一下")
|
||||
}
|
||||
}
|
||||
|
||||
object Stop : SimpleCommand(
|
||||
ConsoleCommandOwner, "stop", "shutdown", "exit",
|
||||
description = "Stop the whole world."
|
||||
) {
|
||||
init {
|
||||
Runtime.getRuntime().addShutdownHook(thread(false) {
|
||||
runBlocking { Stop.execute(ConsoleCommandSender.instance) }
|
||||
})
|
||||
}
|
||||
|
||||
@Handler
|
||||
suspend fun CommandSender.handle() {
|
||||
sendMessage("Stopping mirai-console")
|
||||
kotlin.runCatching {
|
||||
MiraiConsole.job.cancel()
|
||||
}.fold(
|
||||
onSuccess = { sendMessage("mirai-console stopped successfully.") },
|
||||
onFailure = {
|
||||
MiraiConsole.mainLogger.error(it)
|
||||
sendMessage(it.localizedMessage ?: it.message ?: it.toString())
|
||||
}
|
||||
)
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
||||
|
||||
object Login : SimpleCommand(
|
||||
ConsoleCommandOwner, "login",
|
||||
description = "Log in a bot account."
|
||||
) {
|
||||
@Handler
|
||||
suspend fun CommandSender.handle(id: Long, password: String) {
|
||||
sendMessage(
|
||||
kotlin.runCatching {
|
||||
MiraiConsole.addBot(id, password).alsoLogin()
|
||||
}.fold(
|
||||
onSuccess = { "${it.nick} ($id) Login succeed" },
|
||||
onFailure = { throwable ->
|
||||
"Login failed: ${throwable.localizedMessage ?: throwable.message}" +
|
||||
if (this is MessageEventContextAware<*>) {
|
||||
this.fromEvent.selectMessagesUnit {
|
||||
"stacktrace" reply {
|
||||
throwable.stacktraceString
|
||||
}
|
||||
}
|
||||
"test"
|
||||
} else ""
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
@ -53,6 +53,12 @@ object ConsoleCommandOwner : CommandOwner()
|
||||
*/
|
||||
val CommandOwner.registeredCommands: List<Command> get() = InternalCommandManager.registeredCommands.filter { it.owner == this }
|
||||
|
||||
/**
|
||||
* 获取所有已经注册了指令列表.
|
||||
* @see JCommandManager.getRegisteredCommands Java 方法
|
||||
*/
|
||||
val allRegisteredCommands: List<Command> get() = InternalCommandManager.registeredCommands.toList() // copy
|
||||
|
||||
/**
|
||||
* 指令前缀, 如 '/'
|
||||
* @see JCommandManager.getCommandPrefix Java 方法
|
||||
|
@ -14,9 +14,10 @@ package net.mamoe.mirai.console.command
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.MiraiConsoleInternal
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.utils.JavaFriendlyAPI
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import net.mamoe.mirai.message.*
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
|
||||
@ -83,6 +84,12 @@ fun User.asCommandSender(): UserCommandSender {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 表示由 [MessageEvent] 触发的指令
|
||||
*/
|
||||
interface MessageEventContextAware<E : MessageEvent> : MessageEventExtensions<User, Contact> {
|
||||
val fromEvent: E
|
||||
}
|
||||
|
||||
/**
|
||||
* 代表一个用户私聊机器人执行指令
|
||||
@ -99,7 +106,7 @@ sealed class UserCommandSender : CommandSender, BotAwareCommandSender {
|
||||
*/
|
||||
abstract val subject: Contact
|
||||
|
||||
final override val bot: Bot get() = user.bot
|
||||
override val bot: Bot get() = user.bot
|
||||
|
||||
final override suspend fun sendMessage(message: Message) {
|
||||
subject.sendMessage(message)
|
||||
@ -110,15 +117,46 @@ sealed class UserCommandSender : CommandSender, BotAwareCommandSender {
|
||||
* 代表一个用户私聊机器人执行指令
|
||||
* @see Friend.asCommandSender
|
||||
*/
|
||||
class FriendCommandSender(override val user: Friend) : UserCommandSender() {
|
||||
open class FriendCommandSender(final override val user: Friend) : UserCommandSender() {
|
||||
override val subject: Contact get() = user
|
||||
}
|
||||
|
||||
/**
|
||||
* 代表一个用户私聊机器人执行指令
|
||||
* @see Friend.asCommandSender
|
||||
*/
|
||||
class FriendCommandSenderOnMessage(override val fromEvent: FriendMessageEvent) : FriendCommandSender(fromEvent.sender),
|
||||
MessageEventContextAware<FriendMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
||||
override val subject: Contact get() = super.subject
|
||||
override val bot: Bot get() = super.bot
|
||||
}
|
||||
|
||||
/**
|
||||
* 代表一个群成员执行指令.
|
||||
* @see Member.asCommandSender
|
||||
*/
|
||||
open class MemberCommandSender(final override val user: Member) : UserCommandSender() {
|
||||
inline val group: Group get() = user.group
|
||||
override val subject: Contact get() = group
|
||||
}
|
||||
|
||||
/**
|
||||
* 代表一个群成员在群内执行指令.
|
||||
* @see Member.asCommandSender
|
||||
*/
|
||||
class MemberCommandSender(override val user: Member) : UserCommandSender() {
|
||||
inline val group: Group get() = user.group
|
||||
override val subject: Contact get() = group
|
||||
class MemberCommandSenderOnMessage(override val fromEvent: GroupMessageEvent) : MemberCommandSender(fromEvent.sender),
|
||||
MessageEventContextAware<GroupMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
||||
override val subject: Contact get() = super.subject
|
||||
override val bot: Bot get() = super.bot
|
||||
}
|
||||
|
||||
/**
|
||||
* 代表一个群成员通过临时会话私聊机器人执行指令.
|
||||
* @see Member.asCommandSender
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
class TempCommandSenderOnMessage(override val fromEvent: TempMessageEvent) : MemberCommandSender(fromEvent.sender),
|
||||
MessageEventContextAware<TempMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
||||
override val subject: Contact get() = super.subject
|
||||
override val bot: Bot get() = super.bot
|
||||
}
|
@ -9,9 +9,15 @@
|
||||
|
||||
package net.mamoe.mirai.console.command.internal
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.command.*
|
||||
import net.mamoe.mirai.console.job
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.event.Listener
|
||||
import net.mamoe.mirai.event.subscribeAlways
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
|
||||
@ -22,7 +28,7 @@ internal infix fun Array<String>.matchesBeginning(list: List<Any>): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
internal object InternalCommandManager {
|
||||
internal object InternalCommandManager : CoroutineScope by CoroutineScope(MiraiConsole.job) {
|
||||
const val COMMAND_PREFIX = "/"
|
||||
|
||||
@JvmField
|
||||
@ -56,6 +62,18 @@ internal object InternalCommandManager {
|
||||
}
|
||||
return optionalPrefixCommandMap[rawCommand.toLowerCase()]
|
||||
}
|
||||
|
||||
internal val commandListener: Listener<MessageEvent> by lazy {
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
subscribeAlways<MessageEvent>(
|
||||
concurrency = Listener.ConcurrencyKind.CONCURRENT,
|
||||
priority = Listener.EventPriority.HIGH
|
||||
) {
|
||||
if (this.sender.asCommandSender().executeCommand(message) != null) {
|
||||
intercept()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal infix fun Array<out String>.intersectsIgnoringCase(other: Array<out String>): Boolean {
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
object Versions {
|
||||
const val core = "1.1-EA"
|
||||
const val console = "1.1-dev-1"
|
||||
const val console = "1.0-dev-1"
|
||||
const val consoleGraphical = "0.0.7"
|
||||
const val consoleTerminal = "0.1.0"
|
||||
const val consolePure = "0.1.0"
|
||||
|
Loading…
Reference in New Issue
Block a user