Parcourir la source

Update to mirai-core 2.0-RC, add StrangerCommandSender, OtherClientCommandSender, etc.

Him188 il y a 5 ans
Parent
commit
1a2d484a45

+ 4 - 3
backend/mirai-console/src/command/CommandManager.kt

@@ -21,6 +21,7 @@ import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
 import net.mamoe.mirai.console.command.parse.CommandCall
 import net.mamoe.mirai.console.command.parse.CommandCallParser
 import net.mamoe.mirai.console.command.resolve.CommandCallResolver
+import net.mamoe.mirai.console.command.resolve.ResolvedCommandCall
 import net.mamoe.mirai.console.internal.command.CommandManagerImpl
 import net.mamoe.mirai.console.internal.command.CommandManagerImpl.executeCommand
 import net.mamoe.mirai.console.internal.command.executeCommandImpl
@@ -97,7 +98,7 @@ public interface CommandManager {
      *
      * ### 指令解析流程
      * 1. [CommandCallParser] 将 [MessageChain] 解析为 [CommandCall]
-     * 2. [CommandCallResolver] 将 [CommandCall] 解析为 []
+     * 2. [CommandCallResolver] 将 [CommandCall] 解析为 [ResolvedCommandCall]
      * 1. [message] 的第一个消息元素的 [内容][Message.contentToString] 被作为指令名, 在已注册指令列表中搜索. (包含 [Command.prefixOptional] 相关的处理)
      * 2. 参数语法分析.
      *   在当前的实现下, [message] 被以空格和 [SingleMessage] 分割.
@@ -228,7 +229,7 @@ public interface CommandManager {
 public suspend inline fun CommandSender.executeCommand(
     message: String,
     checkPermission: Boolean = true,
-): CommandExecuteResult = CommandManager.executeCommand(this, PlainText(message).asMessageChain(), checkPermission)
+): CommandExecuteResult = CommandManager.executeCommand(this, PlainText(message).toMessageChain(), checkPermission)
 
 
 /**
@@ -242,7 +243,7 @@ public suspend inline fun Command.execute(
     sender: CommandSender,
     vararg arguments: Message = emptyArray(),
     checkPermission: Boolean = true,
-): CommandExecuteResult = CommandManager.executeCommand(sender, this, arguments.asMessageChain(), checkPermission)
+): CommandExecuteResult = CommandManager.executeCommand(sender, this, arguments.toMessageChain(), checkPermission)
 
 /**
  * 执行一个确切的指令

+ 110 - 35
backend/mirai-console/src/command/CommandSender.kt

@@ -9,7 +9,7 @@
 
 @file:Suppress(
     "NOTHING_TO_INLINE", "INAPPLICABLE_JVM_NAME", "FunctionName", "SuspendFunctionOnCoroutineScope",
-    "unused"
+    "unused", "MemberVisibilityCanBePrivate"
 )
 
 package net.mamoe.mirai.console.command
@@ -51,12 +51,16 @@ import kotlin.coroutines.CoroutineContext
  * - [FriendMessageEvent.toCommandSender]
  * - [GroupMessageEvent.toCommandSender]
  * - [TempMessageEvent.toCommandSender]
+ * - [StrangerMessageEvent.toCommandSender]
+ * - [OtherClientMessageEvent.toCommandSender]
  *
  * - [Member.asCommandSender]
- * - [Member.asTempCommandSender]]
- * - [Member.asMemberCommandSender]]
+ * - [NormalMember.asTempCommandSender]
+ * - [Member.asMemberCommandSender]
  * - [Friend.asCommandSender]
  * - [User.asCommandSender]
+ * - [Stranger.asCommandSender]
+ * - [OtherClient.asCommandSender]
  *
  * ## 实现 [CommandSender]
  * 除 Console 前端外, 在任何时候都不要实现 [CommandSender] (包括使用委托). 必须使用上述扩展获取 [CommandSender] 实例.
@@ -75,11 +79,16 @@ import kotlin.coroutines.CoroutineContext
  * - 若在群聊环境, 对应 [CommandSender] 为 [MemberCommandSender]
  * - 若在私聊环境, 对应 [CommandSender] 为 [FriendCommandSender]
  * - 若在临时会话环境, 对应 [CommandSender] 为 [TempCommandSender]
+ * - 若在陌生人会话环境, 对应 [CommandSender] 为 [StrangerCommandSender]
+ * - 若在其他客户端会话环境, 对应 [CommandSender] 为 [OtherClientCommandSender]
  *
  * 三级子类, 当真实收到由用户执行的指令时:
  * - 若在群聊环境, 对应 [CommandSender] 为 [MemberCommandSenderOnMessage]
  * - 若在私聊环境, 对应 [CommandSender] 为 [FriendCommandSenderOnMessage]
  * - 若在临时会话环境, 对应 [CommandSender] 为 [TempCommandSenderOnMessage]
+ * - 若在陌生人会话环境, 对应 [CommandSender] 为 [StrangerCommandSenderOnMessage]
+ * - 若在其他客户端会话环境, 对应 [CommandSender] 为 [OtherClientCommandSenderOnMessage]
+ *
  *
  * 类型关系如图. 箭头指向的是父类.
  *
@@ -199,6 +208,20 @@ public interface CommandSender : CoroutineScope, Permittee {
         @JvmName("from")
         public fun TempMessageEvent.toCommandSender(): TempCommandSenderOnMessage = TempCommandSenderOnMessage(this)
 
+        /**
+         * 构造 [StrangerCommandSenderOnMessage]
+         */
+        @JvmStatic
+        @JvmName("from")
+        public fun StrangerMessageEvent.toCommandSender(): StrangerCommandSenderOnMessage = StrangerCommandSenderOnMessage(this)
+
+        /**
+         * 构造 [OtherClientCommandSenderOnMessage]
+         */
+        @JvmStatic
+        @JvmName("from")
+        public fun OtherClientMessageEvent.toCommandSender(): OtherClientCommandSenderOnMessage = OtherClientCommandSenderOnMessage(this)
+
         /**
          * 构造 [CommandSenderOnMessage]
          */
@@ -209,6 +232,8 @@ public interface CommandSender : CoroutineScope, Permittee {
             is FriendMessageEvent -> toCommandSender()
             is GroupMessageEvent -> toCommandSender()
             is TempMessageEvent -> toCommandSender()
+            is StrangerMessageEvent -> toCommandSender()
+            is OtherClientMessageEvent -> toCommandSender()
             else -> throw IllegalArgumentException("Unsupported MessageEvent: ${this::class.qualifiedNameOrTip}")
         } as CommandSenderOnMessage<T>
 
@@ -244,6 +269,20 @@ public interface CommandSender : CoroutineScope, Permittee {
         @JvmName("of")
         public fun Friend.asCommandSender(): FriendCommandSender = FriendCommandSender(this)
 
+        /**
+         * 得到 [StrangerCommandSender]
+         */
+        @JvmStatic
+        @JvmName("of")
+        public fun Stranger.asCommandSender(): StrangerCommandSender = StrangerCommandSender(this)
+
+        /**
+         * 得到 [OtherClientCommandSender]
+         */
+        @JvmStatic
+        @JvmName("of")
+        public fun OtherClient.asCommandSender(): OtherClientCommandSender = OtherClientCommandSender(this)
+
         /**
          * 得到 [UserCommandSender]
          *
@@ -254,6 +293,7 @@ public interface CommandSender : CoroutineScope, Permittee {
         public fun User.asCommandSender(isTemp: Boolean): UserCommandSender = when (this) {
             is Friend -> this.asCommandSender()
             is Member -> if (isTemp && this is NormalMember) TempCommandSender(this) else MemberCommandSender(this)
+            is Stranger -> this.asCommandSender()
             else -> error("stub")
         }
     }
@@ -469,6 +509,7 @@ public fun CommandSender.getGroupOrNull(): Group? {
  * @see MemberCommandSender 代表一个 [群员][Member] 执行指令
  * @see FriendCommandSender 代表一个 [好友][Friend] 执行指令
  * @see TempCommandSender 代表一个 [群员][Member] 通过临时会话执行指令
+ * @see StrangerCommandSender 代表一个 [陌生人][Stranger] 执行指令
  *
  * @see CommandSenderOnMessage
  */
@@ -524,9 +565,7 @@ public open class FriendCommandSender internal constructor(
  */
 public open class MemberCommandSender internal constructor(
     public final override val user: Member,
-) : AbstractUserCommandSender(),
-    GroupAwareCommandSender,
-    CoroutineScope by user.childScope("MemberCommandSender") {
+) : AbstractUserCommandSender(), GroupAwareCommandSender, CoroutineScope by user.childScope("MemberCommandSender") {
     public final override val group: Group get() = user.group
     public override val subject: Group get() = group
     public override fun toString(): String = "MemberCommandSender($user)"
@@ -546,11 +585,9 @@ public open class MemberCommandSender internal constructor(
  */
 public open class TempCommandSender internal constructor(
     public final override val user: NormalMember,
-) : AbstractUserCommandSender(),
-    GroupAwareCommandSender,
-    CoroutineScope by user.childScope("TempCommandSender") {
+) : AbstractUserCommandSender(), GroupAwareCommandSender, CoroutineScope by user.childScope("TempCommandSender") {
     public override val group: Group get() = user.group
-    public override val subject: Contact get() = group
+    public override val subject: NormalMember get() = user
     public override fun toString(): String = "TempCommandSender($user)"
 
     public override val permitteeId: PermitteeId =
@@ -560,9 +597,48 @@ public open class TempCommandSender internal constructor(
     public override suspend fun sendMessage(message: String): MessageReceipt<Member> = sendMessage(PlainText(message))
 
     @JvmBlockingBridge
-    public override suspend fun sendMessage(message: Message): MessageReceipt<Member> {
-        return user.sendMessage(message) // just throw this error
-    }
+    public override suspend fun sendMessage(message: Message): MessageReceipt<Member> = user.sendMessage(message)
+}
+
+/**
+ * 代表一个 [陌生人][Stranger] 通过私聊执行指令, 但不一定是通过私聊方式, 也有可能是由插件在代码直接执行 ([CommandManager.executeCommand])
+ * @see StrangerCommandSenderOnMessage 代表一个 [陌生人][Stranger] 主动在私聊发送消息执行指令
+ */
+public open class StrangerCommandSender internal constructor(
+    public final override val user: Stranger,
+) : AbstractUserCommandSender(), CoroutineScope by user.childScope("StrangerCommandSender") {
+    public override val subject: Stranger get() = user
+    public override fun toString(): String = "StrangerCommandSender($user)"
+
+    public override val permitteeId: PermitteeId = AbstractPermitteeId.ExactStranger(user.id)
+
+    @JvmBlockingBridge
+    public override suspend fun sendMessage(message: String): MessageReceipt<Stranger> = sendMessage(PlainText(message))
+
+    @JvmBlockingBridge
+    public override suspend fun sendMessage(message: Message): MessageReceipt<Stranger> = user.sendMessage(message)
+}
+
+/**
+ * 代表一个 [其他客户端][OtherClient] 通过私聊执行指令, 但不一定是通过私聊方式, 也有可能是由插件在代码直接执行 ([CommandManager.executeCommand])
+ * @see OtherClientCommandSenderOnMessage 代表一个[其他客户端][OtherClient] 主动在私聊发送消息执行指令
+ */
+public open class OtherClientCommandSender internal constructor(
+    public val client: OtherClient,
+) : AbstractCommandSender(), CoroutineScope by client.childScope("OtherClientCommandSender") {
+    public final override val user: Friend get() = client.bot.asFriend
+    public final override val bot: Bot get() = client.bot
+    public final override val name: String get() = client.bot.nick
+    public override val subject: Friend get() = user
+    public override fun toString(): String = "OtherClientCommandSender($user)"
+
+    public override val permitteeId: PermitteeId = AbstractPermitteeId.ExactStranger(user.id)
+
+    @JvmBlockingBridge
+    public override suspend fun sendMessage(message: String): MessageReceipt<OtherClient> = sendMessage(PlainText(message))
+
+    @JvmBlockingBridge
+    public override suspend fun sendMessage(message: Message): MessageReceipt<OtherClient> = client.sendMessage(message)
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -576,9 +652,7 @@ public open class TempCommandSender internal constructor(
  * @see FriendCommandSenderOnMessage 代表一个真实的 [好友][Friend] 主动在私聊消息执行指令
  * @see TempCommandSenderOnMessage 代表一个 [群员][Member] 主动在临时会话发送消息执行指令
  */
-public interface CommandSenderOnMessage<T : MessageEvent> :
-    CommandSender,
-    MessageEventExtensions<User, Contact> {
+public interface CommandSenderOnMessage<T : MessageEvent> : CommandSender {
 
     /**
      * 消息源 [MessageEvent]
@@ -592,12 +666,7 @@ public interface CommandSenderOnMessage<T : MessageEvent> :
  */
 public class FriendCommandSenderOnMessage internal constructor(
     public override val fromEvent: FriendMessageEvent,
-) : FriendCommandSender(fromEvent.sender),
-    CommandSenderOnMessage<FriendMessageEvent>,
-    MessageEventExtensions<User, Contact> by fromEvent {
-    public override val subject: Friend get() = fromEvent.subject
-    public override val bot: Bot get() = super.bot
-}
+) : FriendCommandSender(fromEvent.sender), CommandSenderOnMessage<FriendMessageEvent>
 
 /**
  * 代表一个真实的 [群员][Member] 主动在群内发送消息执行指令.
@@ -605,22 +674,28 @@ public class FriendCommandSenderOnMessage internal constructor(
  */
 public class MemberCommandSenderOnMessage internal constructor(
     public override val fromEvent: GroupMessageEvent,
-) : MemberCommandSender(fromEvent.sender),
-    CommandSenderOnMessage<GroupMessageEvent>,
-    MessageEventExtensions<User, Contact> by fromEvent {
-    public override val subject: Group get() = fromEvent.subject
-    public override val bot: Bot get() = super.bot
-}
+) : MemberCommandSender(fromEvent.sender), CommandSenderOnMessage<GroupMessageEvent>
 
 /**
  * 代表一个 [群员][Member] 主动在临时会话发送消息执行指令
- * @see TempCommandSender 代表一个 [群员][Member] 通过临时会话执行指令, 但不一定是通过私聊方式
+ * @see TempCommandSender 代表一个 [群员][Member] 执行指令, 但不一定是通过私聊方式
  */
 public class TempCommandSenderOnMessage internal constructor(
     public override val fromEvent: TempMessageEvent,
-) : TempCommandSender(fromEvent.sender as NormalMember),
-    CommandSenderOnMessage<TempMessageEvent>,
-    MessageEventExtensions<User, Contact> by fromEvent {
-    public override val subject: Member get() = fromEvent.subject
-    public override val bot: Bot get() = super.bot
-}
+) : TempCommandSender(fromEvent.sender), CommandSenderOnMessage<TempMessageEvent>
+
+/**
+ * 代表一个 [陌生人][Stranger] 主动在私聊发送消息执行指令
+ * @see StrangerCommandSender 代表一个 [陌生人][Stranger] 执行指令, 但不一定是通过私聊方式
+ */
+public class StrangerCommandSenderOnMessage internal constructor(
+    public override val fromEvent: StrangerMessageEvent,
+) : StrangerCommandSender(fromEvent.sender), CommandSenderOnMessage<StrangerMessageEvent>
+
+/**
+ * 代表一个 [其他客户端][OtherClient] 主动在私聊发送消息执行指令
+ * @see OtherClientCommandSender 代表一个 [其他客户端][OtherClient] 执行指令, 但不一定是通过私聊方式
+ */
+public class OtherClientCommandSenderOnMessage internal constructor(
+    public override val fromEvent: OtherClientMessageEvent,
+) : OtherClientCommandSender(fromEvent.client), CommandSenderOnMessage<OtherClientMessageEvent>

+ 1 - 1
backend/mirai-console/src/command/descriptor/TypeVariant.kt

@@ -71,7 +71,7 @@ public object MessageContentTypeVariant : TypeVariant<MessageContent> {
 public object MessageChainTypeVariant : TypeVariant<MessageChain> {
     @OptIn(ExperimentalStdlibApi::class)
     override val outType: KType = typeOf<MessageChain>()
-    override fun mapValue(valueArgument: Message): MessageChain = valueArgument.asMessageChain()
+    override fun mapValue(valueArgument: Message): MessageChain = valueArgument.toMessageChain()
 }
 
 @ExperimentalCommandDescriptors

+ 2 - 2
backend/mirai-console/src/command/resolve/BuiltInCommandCallResolver.kt

@@ -19,7 +19,7 @@ import net.mamoe.mirai.console.internal.data.classifierAsKClass
 import net.mamoe.mirai.console.util.ConsoleExperimentalApi
 import net.mamoe.mirai.console.util.safeCast
 import net.mamoe.mirai.message.data.EmptyMessageChain
-import net.mamoe.mirai.message.data.asMessageChain
+import net.mamoe.mirai.message.data.toMessageChain
 
 /**
  * Builtin implementation of [CommandCallResolver]
@@ -124,7 +124,7 @@ public object BuiltInCommandCallResolver : CommandCallResolver {
                 val (varargParameter, _)
                     = zipped.removeLast()
 
-                zipped.add(varargParameter to DefaultCommandValueArgument(valueArguments.drop(zipped.size).map { it.value }.asMessageChain()))
+                zipped.add(varargParameter to DefaultCommandValueArgument(valueArguments.drop(zipped.size).map { it.value }.toMessageChain()))
             } else {
                 // add default empty vararg argument
                 val remainingVararg = remainingParameters.find { it.isVararg }

+ 2 - 2
backend/mirai-console/src/internal/command/CommandManagerImpl.kt

@@ -25,7 +25,7 @@ import net.mamoe.mirai.console.internal.util.ifNull
 import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission
 import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope
 import net.mamoe.mirai.message.data.Message
-import net.mamoe.mirai.message.data.asMessageChain
+import net.mamoe.mirai.message.data.toMessageChain
 import net.mamoe.mirai.utils.MiraiLogger
 import java.util.concurrent.locks.ReentrantLock
 
@@ -135,7 +135,7 @@ internal suspend fun executeCommandImpl(
         .intercepted(caller)
         .getOrElse { return CommandExecuteResult.Intercepted(null, null, null, it) }
 
-    val call = message.asMessageChain()
+    val call = message.toMessageChain()
         .parseCommandCall(caller)
         .ifNull { return CommandExecuteResult.UnresolvedCommand(null) }
         .let { raw ->

+ 67 - 22
backend/mirai-console/src/permission/PermitteeId.kt

@@ -19,10 +19,7 @@ import net.mamoe.mirai.console.internal.data.map
 import net.mamoe.mirai.console.internal.permission.parseFromStringImpl
 import net.mamoe.mirai.console.permission.AbstractPermitteeId.*
 import net.mamoe.mirai.console.util.ConsoleExperimentalApi
-import net.mamoe.mirai.contact.Contact
-import net.mamoe.mirai.contact.Group
-import net.mamoe.mirai.contact.Member
-import net.mamoe.mirai.contact.User
+import net.mamoe.mirai.contact.*
 
 /**
  * [被许可人][Permittee] 的标识符
@@ -139,23 +136,23 @@ public interface PermitteeId {
  *          Console                               AnyContact
  *                                                     ↑
  *                                                     |
- *                         +---------------------------+------------------------+
- *                         |                                                    |
- *                      AnyUser                                             AnyGroup
- *                         ↑                                                    ↑
- *                         |                                                    |
- *          +--------------+---------------------+                              |
- *          |              |                     |                              |
- *     AnyFriend           |            AnyMemberFromAnyGroup                   |
- *          ↑              |                     ↑                              |
- *          |              |                     |                              |
- *          |              |            +--------+--------------+               |
- *          |              |            |                       |               |
- *          |              |            |              AnyTempFromAnyGroup      |
- *          |              |            |                       ↑               |
- *          |              |        AnyMember                   |               |
- *          |              |            ↑                       |               |
- *          |          ExactUser        |                       |           ExactGroup
+ *                         +---------------------------+------------------------+---------------------+
+ *                         |                                                    |                     |
+ *                      AnyUser                                             AnyGroup            AnyOtherClient
+ *                         ↑                                                    ↑
+ *                         |                                                    |                     |
+ *          +--------------+---------------------+                              |                     |
+ *          |              |                     |                              |                     |
+ *     AnyFriend           |            AnyMemberFromAnyGroup                   |                     |
+ *          ↑              |                     ↑                              |                     |
+ *          |              |                     |                              |                     |
+ *          |              |            +--------+--------------+               |                     |
+ *          |              |            |                       |               |                     |
+ *          |              |            |              AnyTempFromAnyGroup      |                     |
+ *          |              |            |                       ↑               |                     |
+ *          |              |        AnyMember                   |               |                     |
+ *          |              |            ↑                       |               |                     |
+ *          |          ExactUser        |                       |           ExactGroup         ExactOtherClient
  *          |            ↑   ↑          |                       |
  *          |            |   |          |                       |
  *          +------------+   +----------+                       |
@@ -314,6 +311,32 @@ public sealed class AbstractPermitteeId(
         override fun asString(): String = "t$groupId.$memberId"
     }
 
+    /**
+     * 表示唯一的一个 [陌生人][Stranger]
+     *
+     * - **直接父标识符**: [ExactUser], [AnyStranger]
+     * - **间接父标识符**: [AnyUser], [AnyContact]
+     * - 字符串表示: "s$id"
+     */
+    public data class ExactStranger(
+        public val id: Long,
+    ) : AbstractPermitteeId(ExactUser(id), AnyStranger) {
+        override fun asString(): String = "s$id"
+    }
+
+    /**
+     * 表示唯一的一个 [其他客户端][OtherClient]
+     *
+     * - **直接父标识符**: [AnyOtherClient]
+     * - **间接父标识符**: [AnyContact]
+     * - 字符串表示: "o$id"
+     */
+    public data class ExactOtherClient(
+        public val id: Long,
+    ) : AbstractPermitteeId(AnyOtherClient) {
+        override fun asString(): String = "o$id"
+    }
+
 
     /**
      * 表示任何 [用户][User]
@@ -327,7 +350,29 @@ public sealed class AbstractPermitteeId(
     }
 
     /**
-     * 表示任何 [用户][User]
+     * 表示任何 [陌生人][Stranger]
+     *
+     * - **直接父标识符**: [AnyUser]
+     * - **间接父标识符**: [AnyContact]
+     * - 字符串表示: "s*"
+     */
+    public object AnyStranger : AbstractPermitteeId(AnyUser) {
+        override fun asString(): String = "s*"
+    }
+
+    /**
+     * 表示任何 [其他客户端][OtherClient]
+     *
+     * - **直接父标识符**: [AnyContact]
+     * - **间接父标识符**: 无
+     * - 字符串表示: "o*"
+     */
+    public object AnyOtherClient : AbstractPermitteeId(AnyContact) {
+        override fun asString(): String = "o*"
+    }
+
+    /**
+     * 表示精确 [用户][User]
      *
      * - **直接父标识符**: [AnyUser]
      * - **间接父标识符**: [AnyContact]

+ 2 - 2
buildSrc/src/main/kotlin/Versions.kt

@@ -12,8 +12,8 @@
 import org.gradle.api.attributes.Attribute
 
 object Versions {
-    const val core = "2.0-M2"
-    const val console = "2.0-M2-1-dev-1"
+    const val core = "2.0-RC-dev-8"
+    const val console = "2.0-RC"
     const val consoleGraphical = "0.0.7"
     const val consoleTerminal = console
 

+ 2 - 2
tools/gradle-plugin/src/VersionConstants.kt

@@ -10,6 +10,6 @@
 package net.mamoe.mirai.console.gradle
 
 internal object VersionConstants {
-    const val CONSOLE_VERSION = "2.0-M2-1-dev-1" // value is written here automatically during build
-    const val CORE_VERSION = "2.0-M2" // value is written here automatically during build
+    const val CONSOLE_VERSION = "2.0-RC" // value is written here automatically during build
+    const val CORE_VERSION = "2.0-RC-dev-8" // value is written here automatically during build
 }