Improve CommandSender

This commit is contained in:
Him188 2020-05-14 16:52:11 +08:00
parent b857c8ad41
commit ffe9f5f992
5 changed files with 83 additions and 72 deletions

View File

@ -37,7 +37,7 @@ interface Command {
/** /**
* 执行这个指令. * 执行这个指令.
*/ */
suspend fun onCommand(sender: CommandSender, args: CommandArgs): Boolean suspend fun CommandSender.onCommand(args: CommandArgs): Boolean
} }
/** /**
@ -138,8 +138,8 @@ abstract class BlockingCommand(
owner: PluginBase, owner: PluginBase,
descriptor: CommandDescriptor descriptor: CommandDescriptor
) : PluginCommand(owner, descriptor) { ) : PluginCommand(owner, descriptor) {
final override suspend fun onCommand(sender: CommandSender, args: CommandArgs): Boolean { final override suspend fun CommandSender.onCommand(args: CommandArgs): Boolean {
return withContext(Dispatchers.IO) { onCommandBlocking(sender, args) } return withContext(Dispatchers.IO) { onCommandBlocking(this@onCommand, args) }
} }
abstract fun onCommandBlocking(sender: CommandSender, args: CommandArgs): Boolean abstract fun onCommandBlocking(sender: CommandSender, args: CommandArgs): Boolean

View File

@ -141,8 +141,8 @@ object ExistFriendArgParser : CommandArgParser<Friend>() {
illegalArgument("无法解析~作为默认") illegalArgument("无法解析~作为默认")
} }
val targetID = when (sender) { val targetID = when (sender) {
is GroupContactCommandSender -> sender.realSender.id is MemberCommandSender -> sender.realSender.id
is ContactCommandSender -> sender.contact.id is UserCommandSender -> sender.user.id
else -> illegalArgument("无法解析~作为默认") else -> illegalArgument("无法解析~作为默认")
} }
return try { return try {
@ -177,7 +177,7 @@ object ExistFriendArgParser : CommandArgParser<Friend>() {
override fun parse(raw: SingleMessage, sender: CommandSender): Friend { override fun parse(raw: SingleMessage, sender: CommandSender): Friend {
if (raw is At) { if (raw is At) {
assert(sender is GroupContactCommandSender) assert(sender is MemberCommandSender)
return (sender as BotAware).bot.friends.getOrNull(raw.target) ?: illegalArgument("At的对象非Bot好友") return (sender as BotAware).bot.friends.getOrNull(raw.target) ?: illegalArgument("At的对象非Bot好友")
} else { } else {
error("无法解析 $raw 为好友") error("无法解析 $raw 为好友")
@ -188,8 +188,8 @@ object ExistFriendArgParser : CommandArgParser<Friend>() {
object ExistGroupArgParser : CommandArgParser<Group>() { object ExistGroupArgParser : CommandArgParser<Group>() {
override fun parse(raw: String, sender: CommandSender): Group { override fun parse(raw: String, sender: CommandSender): Group {
//by default //by default
if ((raw == "" || raw == "~") && sender is GroupContactCommandSender) { if ((raw == "" || raw == "~") && sender is MemberCommandSender) {
return sender.contact as Group return sender.user as Group
} }
//from bot to group //from bot to group
if (sender is BotAware) { if (sender is BotAware) {
@ -255,8 +255,8 @@ object ExistMemberArgParser : CommandArgParser<Member>() {
} }
} else { } else {
val bot = sender.bot val bot = sender.bot
if (sender is GroupContactCommandSender) { if (sender is MemberCommandSender) {
val group = sender.contact as Group val group = sender.user as Group
return try { return try {
group.members[raw.toLong()] group.members[raw.toLong()]
} catch (ignored: Exception) { } catch (ignored: Exception) {
@ -288,8 +288,8 @@ object ExistMemberArgParser : CommandArgParser<Member>() {
override fun parse(raw: SingleMessage, sender: CommandSender): Member { override fun parse(raw: SingleMessage, sender: CommandSender): Member {
return if (raw is At) { return if (raw is At) {
checkArgument(sender is GroupContactCommandSender) checkArgument(sender is MemberCommandSender)
(sender.contact as Group).members[raw.target] (sender.user as Group).members[raw.target]
} else { } else {
illegalArgument("无法识别Member" + raw.content) illegalArgument("无法识别Member" + raw.content)
} }

View File

@ -12,10 +12,6 @@
package net.mamoe.mirai.console.command package net.mamoe.mirai.console.command
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.console.utils.isManager
import net.mamoe.mirai.contact.isAdministrator
import net.mamoe.mirai.contact.isOperator
import net.mamoe.mirai.contact.isOwner
/** /**
* 指令权限 * 指令权限
@ -66,7 +62,7 @@ abstract class CommandPermission {
constructor(vararg fromBot: Bot) : this(*fromBot.map { it.id }.toLongArray()) constructor(vararg fromBot: Bot) : this(*fromBot.map { it.id }.toLongArray())
override fun CommandSender.hasPermission(): Boolean { override fun CommandSender.hasPermission(): Boolean {
return this is GroupContactCommandSender && this.bot.id in fromBot && this.realSender.isOperator() return this is MemberCommandSender && this.bot.id in fromBot && this.realSender.isOperator()
} }
/** /**
@ -74,7 +70,7 @@ abstract class CommandPermission {
*/ */
companion object Any : CommandPermission() { companion object Any : CommandPermission() {
override fun CommandSender.hasPermission(): Boolean { override fun CommandSender.hasPermission(): Boolean {
return this is GroupContactCommandSender && this.realSender.isOperator() return this is MemberCommandSender && this.realSender.isOperator()
} }
} }
} }
@ -91,7 +87,7 @@ abstract class CommandPermission {
constructor(vararg fromBot: Bot) : this(*fromBot.map { it.id }.toLongArray()) constructor(vararg fromBot: Bot) : this(*fromBot.map { it.id }.toLongArray())
override fun CommandSender.hasPermission(): Boolean { override fun CommandSender.hasPermission(): Boolean {
return this is GroupContactCommandSender && this.bot.id in fromBot && this.realSender.isOwner() return this is MemberCommandSender && this.bot.id in fromBot && this.realSender.isOwner()
} }
/** /**
@ -99,7 +95,7 @@ abstract class CommandPermission {
*/ */
companion object Any : CommandPermission() { companion object Any : CommandPermission() {
override fun CommandSender.hasPermission(): Boolean { override fun CommandSender.hasPermission(): Boolean {
return this is GroupContactCommandSender && this.realSender.isOwner() return this is MemberCommandSender && this.realSender.isOwner()
} }
} }
} }
@ -116,7 +112,7 @@ abstract class CommandPermission {
constructor(vararg fromBot: Bot) : this(*fromBot.map { it.id }.toLongArray()) constructor(vararg fromBot: Bot) : this(*fromBot.map { it.id }.toLongArray())
override fun CommandSender.hasPermission(): Boolean { override fun CommandSender.hasPermission(): Boolean {
return this is GroupContactCommandSender && this.bot.id in fromBot && this.realSender.isAdministrator() return this is MemberCommandSender && this.bot.id in fromBot && this.realSender.isAdministrator()
} }
/** /**
@ -124,7 +120,7 @@ abstract class CommandPermission {
*/ */
companion object Any : CommandPermission() { companion object Any : CommandPermission() {
override fun CommandSender.hasPermission(): Boolean { override fun CommandSender.hasPermission(): Boolean {
return this is GroupContactCommandSender && this.realSender.isAdministrator() return this is MemberCommandSender && this.realSender.isAdministrator()
} }
} }
} }
@ -141,7 +137,7 @@ abstract class CommandPermission {
constructor(vararg fromBot: Bot) : this(*fromBot.map { it.id }.toLongArray()) constructor(vararg fromBot: Bot) : this(*fromBot.map { it.id }.toLongArray())
override fun CommandSender.hasPermission(): Boolean { override fun CommandSender.hasPermission(): Boolean {
return this is GroupContactCommandSender && this.bot.id in fromBot && this.realSender.isManager return this is MemberCommandSender && this.bot.id in fromBot && this.realSender.isManager
} }
/** /**
@ -149,7 +145,7 @@ abstract class CommandPermission {
*/ */
companion object Any : CommandPermission() { companion object Any : CommandPermission() {
override fun CommandSender.hasPermission(): Boolean { override fun CommandSender.hasPermission(): Boolean {
return this is GroupContactCommandSender && this.realSender.isManager return this is MemberCommandSender && this.realSender.isManager
} }
} }
} }

View File

@ -7,13 +7,18 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("NOTHING_TO_INLINE")
package net.mamoe.mirai.console.command package net.mamoe.mirai.console.command
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.User
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.PlainText
/** /**
* 指令发送者 * 指令发送者
@ -21,13 +26,16 @@ import net.mamoe.mirai.message.data.Message
* @see AbstractCommandSender 请继承于该抽象类 * @see AbstractCommandSender 请继承于该抽象类
*/ */
interface CommandSender { interface CommandSender {
/**
* 与这个 [CommandSender] 相关的 [Bot]. 当通过控制台执行时为 null.
*/
val bot: Bot?
/** /**
* 立刻发送一条消息 * 立刻发送一条消息
*/ */
suspend fun sendMessage(message: Message) suspend fun sendMessage(message: Message)
suspend fun sendMessage(message: String)
/** /**
* 写入要发送的内容 所有内容最后会被以一条发出 * 写入要发送的内容 所有内容最后会被以一条发出
*/ */
@ -37,6 +45,7 @@ interface CommandSender {
fun sendMessageBlocking(message: String) = runBlocking { sendMessage(message) } fun sendMessageBlocking(message: String) = runBlocking { sendMessage(message) }
} }
suspend inline fun CommandSender.sendMessage(message: String) = sendMessage(PlainText(message))
abstract class AbstractCommandSender : CommandSender { abstract class AbstractCommandSender : CommandSender {
internal val builder = StringBuilder() internal val builder = StringBuilder()
@ -56,50 +65,56 @@ abstract class AbstractCommandSender : CommandSender {
* 控制台指令执行者. 代表由控制台执行指令 * 控制台指令执行者. 代表由控制台执行指令
*/ */
object ConsoleCommandSender : AbstractCommandSender() { object ConsoleCommandSender : AbstractCommandSender() {
override val bot: Nothing? get() = null
override suspend fun sendMessage(message: Message) { override suspend fun sendMessage(message: Message) {
TODO() TODO()
// MiraiConsole.logger("[Command]", 0, messageChain.toString()) // MiraiConsole.logger("[Command]", 0, messageChain.toString())
} }
override suspend fun sendMessage(message: String) {
TODO()
// MiraiConsole.logger("[Command]", 0, message)
}
override suspend fun flushMessage() { override suspend fun flushMessage() {
super.flushMessage() super.flushMessage()
builder.clear() builder.clear()
} }
} }
/** inline fun Friend.asCommandSender(): FriendCommandSender = FriendCommandSender(this)
* 指向性CommandSender
* 你可以获得用户在和哪个Bot说指令 inline fun Member.asCommandSender(): MemberCommandSender = MemberCommandSender(this)
*/
interface BotAware { inline fun User.asCommandSender(): UserCommandSender {
val bot: Bot return when (this) {
is Friend -> this.asCommandSender()
is Member -> this.asCommandSender()
else -> error("stub")
}
} }
/** /**
* 联系人指令执行者. 代表由一个 QQ 用户私聊执行指令 * 代表一个用户私聊机器人执行指令
* @see User.asCommandSender
*/ */
@Suppress("MemberVisibilityCanBePrivate") sealed class UserCommandSender : AbstractCommandSender() {
open class ContactCommandSender(override val bot: Bot, val contact: Contact) : AbstractCommandSender(), BotAware { abstract val user: User
override suspend fun sendMessage(message: Message) {
contact.sendMessage(message)
}
override suspend fun sendMessage(message: String) { final override val bot: Bot get() = user.bot
contact.sendMessage(message)
final override suspend fun sendMessage(message: Message) {
user.sendMessage(message)
} }
} }
/** /**
* 联系人指令执行者. 代表由一个 QQ 用户 在群里执行指令 * 代表一个用户私聊机器人执行指令
* @see Friend.asCommandSender
*/ */
open class GroupContactCommandSender( class FriendCommandSender(override val user: Friend) : UserCommandSender()
bot: Bot,
val realSender: Member, /**
subject: Contact * 代表一个群成员在群内执行指令.
) : ContactCommandSender(bot, subject) * @see Member.asCommandSender
*/
class MemberCommandSender(override val user: Member) : UserCommandSender() {
inline val group: Group get() = user.group
}

View File

@ -71,34 +71,34 @@ internal class TestCommands {
) )
} }
inline fun withSender(block: CommandSender.() -> Unit): MessageChain {
val result = MessageChainBuilder()
val sender: CommandSender = object : CommandSender {
override suspend fun sendMessage(message: Message) {
result.add(message)
}
override suspend fun sendMessage(message: String) {
result.add(message)
}
override fun appendMessage(message: String) {
result.add(message)
}
}
sender.let(block)
return result.asMessageChain()
}
@Test @Test
fun testExecute() = runBlocking { fun testExecute() = runBlocking {
TestCommand.register() TestCommand.register()
assertEquals( assertEquals(
"ok", "ok",
withSender { withSender {
execute("test", "ok", "extra") execute("test", "arg")
}.contentToString() }.contentToString()
) )
} }
} }
internal inline fun withSender(block: CommandSender.() -> Unit): MessageChain {
val result = MessageChainBuilder()
val sender: CommandSender = object : CommandSender {
override suspend fun sendMessage(message: Message) {
result.add(message)
}
override suspend fun sendMessage(message: String) {
result.add(message)
}
override fun appendMessage(message: String) {
result.add(message)
}
}
sender.let(block)
return result.asMessageChain()
}