Him188 6 лет назад
Родитель
Сommit
19ca01b427

+ 37 - 9
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt

@@ -9,6 +9,7 @@ import net.mamoe.mirai.Bot.ContactSystem
 import net.mamoe.mirai.contact.*
 import net.mamoe.mirai.network.BotNetworkHandler
 import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
+import net.mamoe.mirai.network.protocol.tim.packet.action.AddFriendPacket
 import net.mamoe.mirai.network.protocol.tim.packet.action.CanAddFriendPacket
 import net.mamoe.mirai.network.protocol.tim.packet.action.CanAddFriendResponse
 import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
@@ -66,7 +67,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) {
         instances.add(this)
     }
 
-    override fun toString(): String = "Bot{qq=${account.id}}"
+    override fun toString(): String = "Bot(${account.id})"
 
     /**
      * [关闭][BotNetworkHandler.close]网络处理器, 取消所有运行在 [BotNetworkHandler] 下的协程.
@@ -158,19 +159,46 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) {
     }
 }
 
-suspend fun ContactSystem.canAddFriend(id: UInt): CanAddFriendResponse =
-    bot.withSession {
-        CanAddFriendPacket(bot.qqAccount, id, bot.sessionKey).sendAndExpect<CanAddFriendResponse>().await()
+@Suppress("ClassName")
+sealed class AddFriendResult {
+
+    open class SUCCESS internal constructor() : AddFriendResult() {
+        companion object : SUCCESS()
+
+        override fun toString(): String = "AddFriendResult(Success)"
+    }
+
+    /**
+     * 对方拒绝添加好友
+     */
+    object REJECTED : AddFriendResult() {
+        override fun toString(): String = "AddFriendResult(Rejected)"
     }
 
+    /**
+     * 这个人已经是好友
+     */
+    object ALREADY_ADDED : SUCCESS() {
+        override fun toString(): String = "AddFriendResult(AlreadyAdded)"
+    }
+}
+
 /**
  * 添加一个好友
  *
  * @param lazyMessage 若需要验证请求时的验证消息.
  */
-suspend fun ContactSystem.addFriend(id: UInt, lazyMessage: () -> String = { "" }): Boolean = when (this.canAddFriend(id)) {
-    is CanAddFriendResponse.AlreadyAdded -> false
-    is CanAddFriendResponse.Rejected -> false
-    is CanAddFriendResponse.RequireVerification -> TODO()
-    is CanAddFriendResponse.ReadyToAdd -> TODO()
+suspend fun ContactSystem.addFriend(id: UInt, lazyMessage: () -> String = { "" }): AddFriendResult = bot.withSession {
+    when (CanAddFriendPacket(bot.qqAccount, id, bot.sessionKey).sendAndExpect<CanAddFriendResponse>().await()) {
+        is CanAddFriendResponse.AlreadyAdded -> AddFriendResult.ALREADY_ADDED
+        is CanAddFriendResponse.Rejected -> AddFriendResult.REJECTED
+        is CanAddFriendResponse.RequireVerification -> {
+
+            TODO()
+        }
+        is CanAddFriendResponse.ReadyToAdd -> {
+            AddFriendPacket(bot.qqAccount, id, bot.sessionKey).sendAndExpect<AddFriendPacket.AddFriendResponse>().await()
+            TODO()
+        }
+    }
 }

+ 1 - 7
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt

@@ -6,7 +6,6 @@ import net.mamoe.mirai.contact.*
 import net.mamoe.mirai.network.BotNetworkHandler
 import net.mamoe.mirai.network.BotSession
 import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket
-import net.mamoe.mirai.network.protocol.tim.packet.action.CanAddFriendResponse
 import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
 import net.mamoe.mirai.network.session
 import net.mamoe.mirai.utils.BotConfiguration
@@ -62,16 +61,11 @@ suspend inline fun Bot.login(noinline configuration: BotConfiguration.() -> Unit
  */
 suspend inline fun Bot.login(): LoginResult = this.network.login(BotConfiguration.Default)
 
-/**
- * 得到可否添加这个人为好友
- */
-suspend inline fun Bot.canAddFriend(id: UInt): CanAddFriendResponse = this.contacts.canAddFriend(id)
-
 /**
  * 添加好友
  */
 @JvmOverloads
-suspend inline fun Bot.addFriend(id: UInt, noinline lazyMessage: () -> String = { "" }) = this.contacts.addFriend(id, lazyMessage)
+suspend inline fun Bot.addFriend(id: UInt, noinline lazyMessage: () -> String = { "" }): AddFriendResult = this.contacts.addFriend(id, lazyMessage)
 
 /**
  * 取得机器人的 QQ 号

+ 8 - 0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribable.kt

@@ -97,4 +97,12 @@ object EventScope : CoroutineScope {
         EventDispatcher + CoroutineExceptionHandler { _, e ->
             MiraiLogger.error("An exception is thrown in EventScope", e)
         }
+}
+
+/**
+ * 可控制是否需要广播这个事件包
+ */
+interface BroadcastControllable : Subscribable {
+    val shouldBroadcast: Boolean
+        get() = true
 }

+ 1 - 1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt

@@ -242,7 +242,7 @@ internal class TIMBotNetworkHandler internal constructor(override inline val bot
 
             when (packet) {
                 is Cancellable -> if ((packet as Cancellable).broadcast(coroutineContext).cancelled) return
-                is Subscribable -> packet.broadcast(coroutineContext)
+                is Subscribable -> if ((packet as? BroadcastControllable)?.shouldBroadcast != false) packet.broadcast(coroutineContext)
             }
 
             // Remove first to release the lock

+ 45 - 39
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/AddContact.kt

@@ -4,12 +4,12 @@ package net.mamoe.mirai.network.protocol.tim.packet.action
 
 import kotlinx.io.core.ByteReadPacket
 import kotlinx.io.core.discardExact
+import kotlinx.io.core.readUByte
 import kotlinx.io.core.readUInt
-import kotlinx.io.core.readUShort
+import net.mamoe.mirai.contact.QQ
 import net.mamoe.mirai.network.BotNetworkHandler
 import net.mamoe.mirai.network.protocol.tim.TIMProtocol
 import net.mamoe.mirai.network.protocol.tim.packet.*
-import net.mamoe.mirai.network.protocol.tim.packet.action.CanAddFriendResponse.State
 import net.mamoe.mirai.network.protocol.tim.packet.event.EventPacket
 import net.mamoe.mirai.utils.io.*
 
@@ -98,49 +98,55 @@ object CanAddFriendPacket : SessionPacketFactory<CanAddFriendResponse>() {
         writeQQ(qq)
     }
 
-    override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): CanAddFriendResponse =
-        CanAddFriendResponse().apply {
-            if (remaining > 20) {//todo check
-                state = State.ALREADY_ADDED
-                return@apply
-            }
-            qq = readUInt()
+    override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): CanAddFriendResponse = with(handler.bot) {
+        if (remaining > 20) {//todo check
+            return CanAddFriendResponse.AlreadyAdded(readUInt().qq())
+        }
+        val qq: QQ = readUInt().qq()
 
-            state = when (val state = readUShort().toUInt()) {
-                0x00u -> State.NOT_REQUIRE_VERIFICATION
-                0x01u -> State.REQUIRE_VERIFICATION//需要验证信息
-                0x99u -> State.ALREADY_ADDED
+        return when (val state = readUByte().toUInt()) {
+            0x00u -> CanAddFriendResponse.ReadyToAdd(qq)
+            0x01u -> CanAddFriendResponse.RequireVerification(qq)
+            0x99u -> CanAddFriendResponse.AlreadyAdded(qq)
 
-                0x03u,
-                0x04u -> State.FAILED
-                else -> throw IllegalStateException(state.toString())
-            }
+            0x03u,
+            0x04u -> CanAddFriendResponse.Rejected(qq)
+            else -> error(state.toString())
         }
+    }
 
 }
 
-class CanAddFriendResponse : EventPacket {
-    var qq: UInt = 0u
-    lateinit var state: State
-
-    enum class State {
-        /**
-         * 已经添加
-         */
-        ALREADY_ADDED,
-        /**
-         * 需要验证信息
-         */
-        REQUIRE_VERIFICATION,
-        /**
-         * 不需要验证信息
-         */
-        NOT_REQUIRE_VERIFICATION,
-        /**
-         * 对方拒绝添加
-         */
-        FAILED,
-    }
+sealed class CanAddFriendResponse : EventPacket {
+    abstract val qq: QQ
+
+    /**
+     * 已经添加
+     */
+    data class AlreadyAdded(
+        override val qq: QQ
+    ) : CanAddFriendResponse()
+
+    /**
+     * 需要验证信息
+     */
+    data class RequireVerification(
+        override val qq: QQ
+    ) : CanAddFriendResponse()
+
+    /**
+     * 不需要验证信息
+     */
+    data class ReadyToAdd(
+        override val qq: QQ
+    ) : CanAddFriendResponse()
+
+    /**
+     * 对方拒绝添加
+     */
+    data class Rejected(
+        override val qq: QQ
+    ) : CanAddFriendResponse()
 }
 
 

+ 7 - 1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Message.kt

@@ -10,6 +10,7 @@ import net.mamoe.mirai.contact.Contact
 import net.mamoe.mirai.contact.Group
 import net.mamoe.mirai.contact.MemberPermission
 import net.mamoe.mirai.contact.QQ
+import net.mamoe.mirai.event.BroadcastControllable
 import net.mamoe.mirai.event.events.BotEvent
 import net.mamoe.mirai.getGroup
 import net.mamoe.mirai.getQQ
@@ -143,7 +144,12 @@ data class FriendMessage(
     val previous: Boolean,
     override val sender: QQ,
     override val message: MessageChain
-) : MessagePacket<QQ>() {
+) : MessagePacket<QQ>(), BroadcastControllable {
+    /**
+     * 是否应被自动广播. 此为内部 API
+     */
+    override val shouldBroadcast: Boolean get() = !previous
+
     override val subject: QQ get() = sender
 }
 

+ 5 - 0
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt

@@ -7,6 +7,7 @@ import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import net.mamoe.mirai.Bot
 import net.mamoe.mirai.BotAccount
+import net.mamoe.mirai.addFriend
 import net.mamoe.mirai.event.Subscribable
 import net.mamoe.mirai.event.subscribeAlways
 import net.mamoe.mirai.event.subscribeMessages
@@ -69,6 +70,10 @@ suspend fun main() {
             }
         }
 
+        startsWith("添加好友", removePrefix = true) {
+            reply(bot.addFriend(it.toUInt()).toString())
+        }
+
     }
 
     bot.network.awaitDisconnection()//等到直到断开连接