mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-27 17:00:14 +08:00
Fix various bugs
This commit is contained in:
parent
c8854b3391
commit
74353d1aaf
@ -11,65 +11,28 @@ package net.mamoe.mirai.console.command
|
|||||||
|
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.cancelAndJoin
|
import kotlinx.coroutines.cancelAndJoin
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import net.mamoe.mirai.Bot
|
|
||||||
import net.mamoe.mirai.alsoLogin
|
import net.mamoe.mirai.alsoLogin
|
||||||
import net.mamoe.mirai.console.MiraiConsole
|
import net.mamoe.mirai.console.MiraiConsole
|
||||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
|
||||||
import net.mamoe.mirai.console.command.CommandManagerImpl.allRegisteredCommands
|
import net.mamoe.mirai.console.command.CommandManagerImpl.allRegisteredCommands
|
||||||
import net.mamoe.mirai.console.command.CommandManagerImpl.register
|
import net.mamoe.mirai.console.command.CommandManagerImpl.register
|
||||||
import net.mamoe.mirai.event.selectMessagesUnit
|
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||||
import net.mamoe.mirai.utils.DirectoryLogger
|
import net.mamoe.mirai.message.nextMessageOrNull
|
||||||
import net.mamoe.mirai.utils.weeksToMillis
|
import net.mamoe.mirai.utils.secondsToMillis
|
||||||
import java.io.File
|
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加一个 [Bot] 实例到全局 Bot 列表, 但不登录.
|
|
||||||
*/
|
|
||||||
public fun MiraiConsole.addBot(id: Long, password: String): Bot {
|
|
||||||
return Bot(id, password) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重定向 [网络日志][networkLoggerSupplier] 到指定目录. 若目录不存在将会自动创建 ([File.mkdirs])
|
|
||||||
* @see DirectoryLogger
|
|
||||||
* @see redirectNetworkLogToDirectory
|
|
||||||
*/
|
|
||||||
fun redirectNetworkLogToDirectory(
|
|
||||||
dir: File = File("logs"),
|
|
||||||
retain: Long = 1.weeksToMillis,
|
|
||||||
identity: (bot: Bot) -> String = { "Net ${it.id}" }
|
|
||||||
) {
|
|
||||||
require(!dir.isFile) { "dir must not be a file" }
|
|
||||||
dir.mkdirs()
|
|
||||||
networkLoggerSupplier = { DirectoryLogger(identity(it), dir, retain) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun redirectBotLogToDirectory(
|
|
||||||
dir: File = File("logs"),
|
|
||||||
retain: Long = 1.weeksToMillis,
|
|
||||||
identity: (bot: Bot) -> String = { "Net ${it.id}" }
|
|
||||||
) {
|
|
||||||
require(!dir.isFile) { "dir must not be a file" }
|
|
||||||
dir.mkdirs()
|
|
||||||
botLoggerSupplier = { DirectoryLogger(identity(it), dir, retain) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fileBasedDeviceInfo()
|
|
||||||
this.loginSolver = this@addBot.frontEnd.createLoginSolver()
|
|
||||||
redirectNetworkLogToDirectory()
|
|
||||||
// redirectBotLogToDirectory()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ConsoleExperimentalAPI
|
||||||
@Suppress("EXPOSED_SUPER_INTERFACE")
|
@Suppress("EXPOSED_SUPER_INTERFACE")
|
||||||
public interface BuiltInCommand : Command, BuiltInCommandInternal
|
public interface BuiltInCommand : Command, BuiltInCommandInternal
|
||||||
|
|
||||||
// for identification
|
// for identification
|
||||||
internal interface BuiltInCommandInternal : Command
|
internal interface BuiltInCommandInternal : Command
|
||||||
|
|
||||||
|
@ConsoleExperimentalAPI
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
public object BuiltInCommands {
|
public object BuiltInCommands {
|
||||||
|
|
||||||
@ -89,8 +52,9 @@ public object BuiltInCommands {
|
|||||||
), BuiltInCommand {
|
), BuiltInCommand {
|
||||||
@Handler
|
@Handler
|
||||||
public suspend fun CommandSender.handle() {
|
public suspend fun CommandSender.handle() {
|
||||||
sendMessage("现在有指令: ${allRegisteredCommands.joinToString { it.primaryName }}")
|
sendMessage(allRegisteredCommands.joinToString {
|
||||||
sendMessage("帮助还没写, 将就一下")
|
it.usage + "\n\n"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,22 +94,20 @@ public object BuiltInCommands {
|
|||||||
), BuiltInCommand {
|
), BuiltInCommand {
|
||||||
@Handler
|
@Handler
|
||||||
public suspend fun CommandSender.handle(id: Long, password: String) {
|
public suspend fun CommandSender.handle(id: Long, password: String) {
|
||||||
|
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
MiraiConsole.addBot(id, password).alsoLogin()
|
MiraiConsole.addBot(id, password).alsoLogin()
|
||||||
}.fold(
|
}.fold(
|
||||||
onSuccess = { sendMessage("${it.nick} ($id) Login succeed") },
|
onSuccess = { sendMessage("${it.nick} ($id) Login successful") },
|
||||||
onFailure = { throwable ->
|
onFailure = { throwable ->
|
||||||
sendMessage(
|
sendMessage(
|
||||||
"Login failed: ${throwable.localizedMessage ?: throwable.message ?: throwable.toString()}" +
|
"Login failed: ${throwable.localizedMessage ?: throwable.message ?: throwable.toString()}" +
|
||||||
if (this is MessageEventContextAware<*>) {
|
if (this is MessageEventContextAware<*>) {
|
||||||
this.fromEvent.selectMessagesUnit {
|
CommandManagerImpl.launch {
|
||||||
"stacktrace" reply {
|
fromEvent.nextMessageOrNull(60.secondsToMillis) { it.message.contentEquals("stacktrace") }
|
||||||
throwable.stackTraceToString()
|
|
||||||
}
|
}
|
||||||
}
|
"\n 1 分钟内发送 stacktrace 以获取堆栈信息"
|
||||||
"test"
|
} else ""
|
||||||
} else "")
|
)
|
||||||
|
|
||||||
throw throwable
|
throw throwable
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,9 @@ public interface CommandManager {
|
|||||||
* @return
|
* @return
|
||||||
* 若已有重名指令, 且 [override] 为 `false`, 返回 `false`;
|
* 若已有重名指令, 且 [override] 为 `false`, 返回 `false`;
|
||||||
* 若已有重名指令, 但 [override] 为 `true`, 覆盖原有指令并返回 `true`.
|
* 若已有重名指令, 但 [override] 为 `true`, 覆盖原有指令并返回 `true`.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 注意: [内建指令][BuiltInCommands] 也可以被覆盖.
|
||||||
*/
|
*/
|
||||||
public fun Command.register(override: Boolean = false): Boolean
|
public fun Command.register(override: Boolean = false): Boolean
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ import net.mamoe.mirai.event.Listener
|
|||||||
import net.mamoe.mirai.event.subscribeAlways
|
import net.mamoe.mirai.event.subscribeAlways
|
||||||
import net.mamoe.mirai.message.MessageEvent
|
import net.mamoe.mirai.message.MessageEvent
|
||||||
import net.mamoe.mirai.message.data.MessageChain
|
import net.mamoe.mirai.message.data.MessageChain
|
||||||
|
import net.mamoe.mirai.message.data.MessageContent
|
||||||
|
import net.mamoe.mirai.message.data.content
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
internal object CommandManagerImpl : CommandManager, CoroutineScope by CoroutineScope(MiraiConsole.job) {
|
internal object CommandManagerImpl : CommandManager, CoroutineScope by CoroutineScope(MiraiConsole.job) {
|
||||||
@ -60,7 +62,7 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
|
|||||||
concurrency = Listener.ConcurrencyKind.CONCURRENT,
|
concurrency = Listener.ConcurrencyKind.CONCURRENT,
|
||||||
priority = Listener.EventPriority.HIGH
|
priority = Listener.EventPriority.HIGH
|
||||||
) {
|
) {
|
||||||
if (this.sender.asCommandSender().executeCommand(message) != null) {
|
if (this.toCommandSender().executeCommand(message) != null) {
|
||||||
intercept()
|
intercept()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,7 +131,8 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
|
|||||||
|
|
||||||
override suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
|
override suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
|
||||||
if (message.isEmpty()) return null
|
if (message.isEmpty()) return null
|
||||||
return matchAndExecuteCommandInternal(message, message[0].toString().substringBefore(' '))
|
val msg = message.filterIsInstance<MessageContent>()
|
||||||
|
return matchAndExecuteCommandInternal(msg, msg[0].content.substringBefore(' '))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean) {
|
override suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean) {
|
||||||
|
@ -10,9 +10,10 @@
|
|||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
|
|
||||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||||
|
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [executeCommand] 中, [CommandSender] 未拥有 [Command.permission] 所要求的权限时抛出的异常.
|
* 在 [CommandManager.executeCommand] 中, [CommandSender] 未拥有 [Command.permission] 所要求的权限时抛出的异常.
|
||||||
*
|
*
|
||||||
* 总是作为 [CommandExecutionException.cause].
|
* 总是作为 [CommandExecutionException.cause].
|
||||||
*/
|
*/
|
||||||
|
@ -12,7 +12,7 @@ package net.mamoe.mirai.console.command
|
|||||||
/**
|
/**
|
||||||
* 无参数解析, 接收原生参数的指令.
|
* 无参数解析, 接收原生参数的指令.
|
||||||
*/
|
*/
|
||||||
public abstract class RawCommand(
|
public abstract class RawCommand @JvmOverloads constructor(
|
||||||
public override val owner: CommandOwner,
|
public override val owner: CommandOwner,
|
||||||
public override vararg val names: String,
|
public override vararg val names: String,
|
||||||
public override val usage: String = "<no usages given>",
|
public override val usage: String = "<no usages given>",
|
||||||
|
@ -17,13 +17,40 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
|
|
||||||
import net.mamoe.mirai.console.command.description.CommandArgumentContext
|
import net.mamoe.mirai.console.command.description.*
|
||||||
import net.mamoe.mirai.console.command.description.CommandArgumentContextAware
|
|
||||||
import net.mamoe.mirai.console.command.description.EmptyCommandArgumentContext
|
|
||||||
import net.mamoe.mirai.console.command.description.plus
|
|
||||||
import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand
|
import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand
|
||||||
import net.mamoe.mirai.console.internal.command.SimpleCommandSubCommandAnnotationResolver
|
import net.mamoe.mirai.console.internal.command.SimpleCommandSubCommandAnnotationResolver
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单指令. 参数支持自动解析. [CommandArgumentParser]
|
||||||
|
*
|
||||||
|
* Kotlin 实现:
|
||||||
|
* ```
|
||||||
|
* object MySimpleCommand : SimpleCommand(
|
||||||
|
* MyPlugin, "tell",
|
||||||
|
* description = "Message somebody",
|
||||||
|
* usage = "/tell <target> <message>"
|
||||||
|
* ) {
|
||||||
|
* @Handler
|
||||||
|
* suspend fun CommandSender.onCommand(target: User, message: String) {
|
||||||
|
* target.sendMessage(message)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Java 实现:
|
||||||
|
* ```java
|
||||||
|
* public final class MySimpleCommand extends SimpleCommand {
|
||||||
|
* private MySimpleCommand() {
|
||||||
|
* super(MyPlugin.INSTANCE, new String[]{ "tell" }, "Message somebody", "/tell <target> <message>")
|
||||||
|
* }
|
||||||
|
* @Handler
|
||||||
|
* public void onCommand(CommandSender sender, User target, String message) {
|
||||||
|
* target.sendMessage(message)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
public abstract class SimpleCommand @JvmOverloads constructor(
|
public abstract class SimpleCommand @JvmOverloads constructor(
|
||||||
owner: CommandOwner,
|
owner: CommandOwner,
|
||||||
vararg names: String,
|
vararg names: String,
|
||||||
|
Loading…
Reference in New Issue
Block a user