From 9756a8dfa8aee630b8a0fdcfbafbf1370a5e0060 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Mon, 27 Sep 2021 16:09:42 +0100
Subject: [PATCH] Fix duplicated `BotJoinGroupEvent` when
 `BotInvitedJoinGroupRequestEvent` is accepted by bot. Fixes #1213

---
 .../group/GroupOrMemberListNoticeProcessor.kt |  6 ++-
 .../notice/processors/BotInvitedJoinTest.kt   | 51 +++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupOrMemberListNoticeProcessor.kt b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupOrMemberListNoticeProcessor.kt
index 77c4ca93a..cdaa41037 100644
--- a/mirai-core/src/commonMain/kotlin/network/notice/group/GroupOrMemberListNoticeProcessor.kt
+++ b/mirai-core/src/commonMain/kotlin/network/notice/group/GroupOrMemberListNoticeProcessor.kt
@@ -137,9 +137,13 @@ internal class GroupOrMemberListNoticeProcessor(
     private suspend fun NoticePipelineContext.processGroupJoin33(data: MsgComm.Msg) = data.context {
         msgBody.msgContent.read {
             val groupUin = Mirai.calculateGroupUinByGroupCode(readUInt().toLong())
-            val group = bot.getGroupByUin(groupUin) ?: bot.addNewGroupByUin(groupUin) ?: return
+            if (remaining < 5) return
             discardExact(1)
             val joinedMemberUin = readUInt().toLong()
+
+            if (joinedMemberUin == bot.id && bot.getGroupByUin(groupUin) != null) return // duplicate
+
+            val group = bot.getGroupByUin(groupUin) ?: bot.addNewGroupByUin(groupUin) ?: return
             val joinType = readByte().toInt()
             val invitorUin = readUInt().toLong()
             when (joinType) {
diff --git a/mirai-core/src/commonTest/kotlin/notice/processors/BotInvitedJoinTest.kt b/mirai-core/src/commonTest/kotlin/notice/processors/BotInvitedJoinTest.kt
index e5f145f9b..867b03448 100644
--- a/mirai-core/src/commonTest/kotlin/notice/processors/BotInvitedJoinTest.kt
+++ b/mirai-core/src/commonTest/kotlin/notice/processors/BotInvitedJoinTest.kt
@@ -100,6 +100,57 @@ internal class BotInvitedJoinTest : AbstractNoticeProcessorTest() {
 
     }
 
+    @Test
+    suspend fun `invited join, accepted`() {
+        // https://github.com/mamoe/mirai/issues/1213
+        suspend fun runTest() = use(
+            createContext = { bot, attributes ->
+                object : NoticeProcessorPipelineImpl.ContextImpl(bot, attributes) {
+                    override suspend fun QQAndroidBot.addNewGroupByUin(groupUin: Long): GroupImpl {
+                        assertEquals(204230203, groupUin) // uin of 2230203
+                        return bot.addGroup(2230203, 1230001, name = "testtest").apply {
+                            addMember(1230003, permission = MemberPermission.MEMBER)
+                            addMember(1230001, permission = MemberPermission.OWNER)
+                        }
+                    }
+                }
+            }
+        ) {
+            net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.Msg(
+                msgHead = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.MsgHead(
+                    fromUin = 2230203,
+                    toUin = 1230002,
+                    msgType = 33,
+                    msgSeq = 593,
+                    msgTime = 1632,
+                    msgUid = 14411518,
+                    authUin = 1230002,
+                    authNick = "user2",
+                    extGroupKeyInfo = net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm.ExtGroupKeyInfo(
+                        curMaxSeq = 1652,
+                        curTime = 16327,
+                    ),
+                    authSex = 2,
+                ),
+                msgBody = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.MsgBody(
+                    msgContent = "00 22 07 BB 01 00 12 C4 B2 03 00 12 C4 B1 06 B4 B4 BD A8 D5 DF 00 30 31 39 37 31 44 32 34 34 31 44 30 42 30 45 41 44 42 35 35 32 46 43 33 31 35 32 36 33 43 45 39 39 43 45 43 43 35 46 30 35 45 32 46 38 39 44 41 33".hexToBytes(),
+                ),
+            )
+        }
+
+        setBot(1230002)
+
+        runTest().toList().run {
+            assertEquals(1, size, toString())
+            get(0).run {
+                assertIs<BotJoinGroupEvent.Invite>(this)
+                assertEquals(1230001, invitor.id)
+            }
+        }
+
+    }
+
+
     @Test
     suspend fun `invitation accepted`() {
         suspend fun runTest() =