|
|
@@ -0,0 +1,443 @@
|
|
|
+/*
|
|
|
+ * Copyright 2019-2021 Mamoe Technologies and contributors.
|
|
|
+ *
|
|
|
+ * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
|
|
+ * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
|
|
+ *
|
|
|
+ * https://github.com/mamoe/mirai/blob/master/LICENSE
|
|
|
+ */
|
|
|
+
|
|
|
+package net.mamoe.mirai.internal.network.notice
|
|
|
+
|
|
|
+import kotlinx.coroutines.CancellationException
|
|
|
+import kotlinx.coroutines.cancel
|
|
|
+import kotlinx.coroutines.sync.withLock
|
|
|
+import kotlinx.io.core.discardExact
|
|
|
+import kotlinx.io.core.readUByte
|
|
|
+import kotlinx.io.core.readUInt
|
|
|
+import net.mamoe.mirai.Mirai
|
|
|
+import net.mamoe.mirai.contact.MemberPermission.*
|
|
|
+import net.mamoe.mirai.event.events.*
|
|
|
+import net.mamoe.mirai.internal.contact.addNewNormalMember
|
|
|
+import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
|
|
+import net.mamoe.mirai.internal.getGroupByUin
|
|
|
+import net.mamoe.mirai.internal.message.contextualBugReportException
|
|
|
+import net.mamoe.mirai.internal.network.components.ContactUpdater
|
|
|
+import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
|
|
|
+import net.mamoe.mirai.internal.network.components.PipelineContext
|
|
|
+import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC
|
|
|
+import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
|
|
|
+import net.mamoe.mirai.internal.network.protocol.data.proto.*
|
|
|
+import net.mamoe.mirai.internal.utils._miraiContentToString
|
|
|
+import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
|
|
+import net.mamoe.mirai.internal.utils.parseToMessageDataList
|
|
|
+import net.mamoe.mirai.internal.utils.toMemberInfo
|
|
|
+import net.mamoe.mirai.utils.MiraiLogger
|
|
|
+import net.mamoe.mirai.utils.context
|
|
|
+import net.mamoe.mirai.utils.debug
|
|
|
+import net.mamoe.mirai.utils.read
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * @see BotJoinGroupEvent
|
|
|
+ * @see MemberJoinEvent
|
|
|
+ *
|
|
|
+ * @see BotLeaveEvent
|
|
|
+ * @see MemberLeaveEvent
|
|
|
+ *
|
|
|
+ * @see MemberPermissionChangeEvent
|
|
|
+ * @see BotGroupPermissionChangeEvent
|
|
|
+ */
|
|
|
+internal class GroupListNoticeProcessor(
|
|
|
+ private val logger: MiraiLogger
|
|
|
+) : MixedNoticeProcessor(), GroupEventProcessorContext {
|
|
|
+
|
|
|
+ override suspend fun PipelineContext.processImpl(data: MsgType0x210) {
|
|
|
+ if (data.uSubMsgType != 0x44L) return
|
|
|
+ val msg = data.vProtobuf.loadAs(Submsgtype0x44.Submsgtype0x44.MsgBody.serializer())
|
|
|
+ if (msg.msgGroupMsgSync == null) return
|
|
|
+
|
|
|
+ when (msg.msgGroupMsgSync.msgType) {
|
|
|
+ 1, 2 -> {
|
|
|
+ bot.components[ContactUpdater].groupListModifyLock.withLock {
|
|
|
+ bot.createGroupForBot(Mirai.calculateGroupUinByGroupCode(msg.msgGroupMsgSync.grpCode))?.let {
|
|
|
+ collect(BotJoinGroupEvent.Active(it))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @see MemberJoinEvent.Invite
|
|
|
+ * @see MemberLeaveEvent.Quit
|
|
|
+ */
|
|
|
+ override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) = data.context {
|
|
|
+ if (data.kind != 0x10) return
|
|
|
+ val proto = data.buf.loadAs(TroopTips0x857.NotifyMsgBody.serializer(), offset = 1)
|
|
|
+ if (proto.optEnumType != 1) return
|
|
|
+ val tipsInfo = proto.optMsgGraytips ?: return
|
|
|
+
|
|
|
+ val message = tipsInfo.optBytesContent.decodeToString()
|
|
|
+ // 机器人信息
|
|
|
+ when (tipsInfo.robotGroupOpt) {
|
|
|
+ // 添加
|
|
|
+ 1 -> {
|
|
|
+ val dataList = message.parseToMessageDataList()
|
|
|
+ val invitor = dataList.first().let { messageData ->
|
|
|
+ group.getOrFail(messageData.data.toLong())
|
|
|
+ }
|
|
|
+ val member = dataList.last().let { messageData ->
|
|
|
+ group.addNewNormalMember(messageData.toMemberInfo())
|
|
|
+ }
|
|
|
+ collect(MemberJoinEvent.Invite(member, invitor))
|
|
|
+ }
|
|
|
+ // 移除
|
|
|
+ 2 -> {
|
|
|
+ message.parseToMessageDataList().first().let {
|
|
|
+ val member = group.getOrFail(it.data.toLong())
|
|
|
+ group.members.delegate.remove(member)
|
|
|
+ collect(MemberLeaveEvent.Quit(member))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ else -> {
|
|
|
+ logger.debug { "Unknown robotGroupOpt ${tipsInfo.robotGroupOpt}, message=$message" }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return markAsConsumed()
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @see MemberJoinEvent.Invite
|
|
|
+ * @see BotJoinGroupEvent.Invite
|
|
|
+ * @see MemberJoinEvent.Active
|
|
|
+ * @see BotJoinGroupEvent.Active
|
|
|
+ */
|
|
|
+ override suspend fun PipelineContext.processImpl(data: MsgComm.Msg) = data.context {
|
|
|
+ if (data.msgHead.msgType != 33) return
|
|
|
+ bot.components[ContactUpdater].groupListModifyLock.withLock {
|
|
|
+ msgBody.msgContent.read {
|
|
|
+ val groupUin = Mirai.calculateGroupUinByGroupCode(readUInt().toLong())
|
|
|
+ val group =
|
|
|
+ bot.getGroupByUin(groupUin) ?: bot.createGroupForBot(groupUin) ?: return markAsConsumed()
|
|
|
+ discardExact(1)
|
|
|
+ val joinedMemberUin = readUInt().toLong()
|
|
|
+ val joinType = readByte().toInt()
|
|
|
+ val invitorUin = readUInt().toLong()
|
|
|
+ when (joinType) {
|
|
|
+ // 邀请加入
|
|
|
+ -125, 3 -> {
|
|
|
+ val invitor = group[invitorUin] ?: return markAsConsumed()
|
|
|
+ collected += if (joinedMemberUin == bot.id) {
|
|
|
+ BotJoinGroupEvent.Invite(invitor)
|
|
|
+ } else {
|
|
|
+ MemberJoinEvent.Invite(group.addNewNormalMember(getNewMemberInfo()), invitor)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 通过群员分享的二维码/直接加入
|
|
|
+ -126, 2 -> {
|
|
|
+ collected += if (joinedMemberUin == bot.id) {
|
|
|
+ BotJoinGroupEvent.Active(group)
|
|
|
+ } else {
|
|
|
+ MemberJoinEvent.Active(group.addNewNormalMember(getNewMemberInfo()))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 忽略
|
|
|
+ else -> {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 邀请入群
|
|
|
+ // package: 27 0B 60 E7 01 CA CC 69 8B 83 44 71 47 90 06 B9 DC C0 ED D4 B1 00 30 33 44 30 42 38 46 30 39 37 32 38 35 43 34 31 38 30 33 36 41 34 36 31 36 31 35 32 37 38 46 46 43 30 41 38 30 36 30 36 45 38 31 43 39 41 34 38 37
|
|
|
+ // package: groupUin + 01 CA CC 69 8B 83 + invitorUin + length(06) + string + magicKey
|
|
|
+
|
|
|
+
|
|
|
+ // 主动入群, 直接加入: msgContent=27 0B 60 E7 01 76 E4 B8 DD 82 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 42 39 41 30 33 45 38 34 30 39 34 42 46 30 45 32 45 38 42 31 43 43 41 34 32 42 38 42 44 42 35 34 44 42 31 44 32 32 30 46 30 38 39 46 46 35 41 38
|
|
|
+ // 主动直接加入 27 0B 60 E7 01 76 E4 B8 DD 82 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 33 30 45 38 42 31 33 46 41 41 31 33 46 38 31 35 34 41 38 33 32 37 31 43 34 34 38 35 33 35 46 45 31 38 32 43 39 42 43 46 46 32 44 39 39 46 41 37
|
|
|
+
|
|
|
+ // 有人被邀请(经过同意后)加入 27 0B 60 E7 01 76 E4 B8 DD 83 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 34 30 34 38 32 33 38 35 37 41 37 38 46 33 45 37 35 38 42 39 38 46 43 45 44 43 32 41 30 31 36 36 30 34 31 36 39 35 39 30 38 39 30 39 45 31 34 34
|
|
|
+ // 搜索到群, 直接加入 27 0B 60 E7 01 07 6E 47 BA 82 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 32 30 39 39 42 39 41 46 32 39 41 35 42 33 46 34 32 30 44 36 44 36 39 35 44 38 45 34 35 30 46 30 45 30 38 45 31 41 39 42 46 46 45 32 30 32 34 35
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ///////////////////////////////////////////////////////////////////////////
|
|
|
+ // Structmsg.StructMsg
|
|
|
+ ///////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+ override suspend fun PipelineContext.processImpl(data: Structmsg.StructMsg) = data.msg.context {
|
|
|
+ markAsConsumed()
|
|
|
+ if (this == null) return
|
|
|
+ when (subType) {
|
|
|
+ // 处理被邀请入群 或 处理成员入群申请
|
|
|
+ 1 -> when (groupMsgType) {
|
|
|
+ 1 -> {
|
|
|
+ // 成员申请入群
|
|
|
+ MemberJoinRequestEvent(
|
|
|
+ bot, data.msgSeq, msgAdditional,
|
|
|
+ data.reqUin, groupCode, groupName, reqUinNick
|
|
|
+ )
|
|
|
+ }
|
|
|
+ 2 -> {
|
|
|
+ // Bot 被邀请入群
|
|
|
+ BotInvitedJoinGroupRequestEvent(
|
|
|
+ bot, data.msgSeq, actionUin,
|
|
|
+ groupCode, groupName, actionUinNick
|
|
|
+ )
|
|
|
+ }
|
|
|
+ 22 -> {
|
|
|
+ // 成员邀请入群
|
|
|
+ MemberJoinRequestEvent(
|
|
|
+ bot, data.msgSeq, msgAdditional,
|
|
|
+ data.reqUin, groupCode, groupName, reqUinNick, actionUin
|
|
|
+ )
|
|
|
+ }
|
|
|
+ else -> throw contextualBugReportException(
|
|
|
+ "parse SystemMsgNewGroup, subType=1",
|
|
|
+ this._miraiContentToString(),
|
|
|
+ additional = "并尽量描述此时机器人是否正被邀请加入群, 或者是有有新群员加入此群"
|
|
|
+ )
|
|
|
+ }
|
|
|
+ 2 -> { // 被邀请入群, 自动同意, 不需处理
|
|
|
+
|
|
|
+// val group = bot.getNewGroup(groupCode) ?: return null
|
|
|
+// val invitor = group[actionUin]
|
|
|
+//
|
|
|
+// BotJoinGroupEvent.Invite(invitor)
|
|
|
+ }
|
|
|
+ 3 -> { // 已被请他管理员处理
|
|
|
+ }
|
|
|
+ 5 -> {
|
|
|
+ val group = bot.getGroup(groupCode) ?: return
|
|
|
+ when (groupMsgType) {
|
|
|
+ 3 -> {
|
|
|
+ // https://github.com/mamoe/mirai/issues/651
|
|
|
+ // msgDescribe=将你设置为管理员
|
|
|
+ // msgTitle=管理员设置
|
|
|
+ }
|
|
|
+ 13 -> {
|
|
|
+ // 成员主动退出, 机器人是管理员, 接到通知
|
|
|
+ // 但无法获取是哪个成员.
|
|
|
+ }
|
|
|
+ 7 -> { // 机器人被踢
|
|
|
+ val operator = group[actionUin] ?: return
|
|
|
+ BotLeaveEvent.Kick(operator)
|
|
|
+ }
|
|
|
+ else -> {
|
|
|
+ throw contextualBugReportException(
|
|
|
+ "解析 NewContact.SystemMsgNewGroup, subType=5, groupMsgType=$groupMsgType",
|
|
|
+ this._miraiContentToString(),
|
|
|
+ null,
|
|
|
+ "并描述此时机器人是否被踢出群等"
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else -> throw contextualBugReportException(
|
|
|
+ "解析 NewContact.SystemMsgNewGroup, subType=$subType, groupMsgType=$groupMsgType",
|
|
|
+ forDebug = this._miraiContentToString(),
|
|
|
+ additional = "并尽量描述此时机器人是否正被邀请加入群, 或者是有有新群员加入此群"
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ///////////////////////////////////////////////////////////////////////////
|
|
|
+ // OnlinePushTrans.PbMsgInfo
|
|
|
+ ///////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+ override suspend fun PipelineContext.processImpl(data: OnlinePushTrans.PbMsgInfo) {
|
|
|
+ markAsConsumed()
|
|
|
+ when (data.msgType) {
|
|
|
+ 44 -> data.msgData.read {
|
|
|
+ discardExact(5)
|
|
|
+ val kind = readUByte().toInt()
|
|
|
+ if (kind == 0xFF) {
|
|
|
+ val from = readUInt().toLong()
|
|
|
+ val to = readUInt().toLong()
|
|
|
+
|
|
|
+ handleGroupOwnershipTransfer(data, from, to)
|
|
|
+ } else {
|
|
|
+ val var5 = if (kind == 0 || kind == 1) 0 else readUInt().toInt()
|
|
|
+ val target = readUInt().toLong()
|
|
|
+
|
|
|
+ if (var5 == 0) {
|
|
|
+ val newPermission = if (remaining == 1L) readByte() else return
|
|
|
+ handlePermissionChange(data, target, newPermission.toInt())
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 34 -> {
|
|
|
+ /* quit
|
|
|
+ 27 0B 60 E7
|
|
|
+ 01
|
|
|
+ 2F 55 7C B8
|
|
|
+ 82
|
|
|
+ 00 30 42 33 32 46 30 38 33 32 39 32 35 30 31 39 33 45 46 32 45 30 36 35 41 35 41 33 42 37 35 43 41 34 46 37 42 38 42 38 42 44 43 35 35 34 35 44 38 30
|
|
|
+ */
|
|
|
+ /* kick
|
|
|
+ 27 0B 60 E7
|
|
|
+ 01
|
|
|
+ A8 32 51 A1
|
|
|
+ 83 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 39 32 46 45 30 36 31 41 33 37 36 43 44 35 37 35 37 39 45 37 32 34 44 37 37 30 36 46 39 39 43 35 35 33 33 31 34 44 32 44 46 35 45 42 43 31 31 36
|
|
|
+ */
|
|
|
+
|
|
|
+ data.msgData.read {
|
|
|
+ readUInt().toLong() // groupCode
|
|
|
+ readByte().toInt() // follow type
|
|
|
+ val target = readUInt().toLong()
|
|
|
+ val kind = readUByte().toInt()
|
|
|
+ val operator = readUInt().toLong()
|
|
|
+ val groupUin = data.fromUin
|
|
|
+ handleLeave(target, kind, operator, groupUin)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else -> {
|
|
|
+ when {
|
|
|
+ data.msgType == 529 && data.msgSubtype == 9 -> {
|
|
|
+ /*
|
|
|
+ PbMsgInfo#1773430973 {
|
|
|
+fromUin=0x0000000026BA1173(649728371)
|
|
|
+generalFlag=0x00000001(1)
|
|
|
+msgData=0A 07 70 72 69 6E 74 65 72 10 02 1A CD 02 0A 1F 53 61 6D 73 75 6E 67 20 4D 4C 2D 31 38 36 30 20 53 65 72 69 65 73 20 28 55 53 42 30 30 31 29 0A 16 4F 6E 65 4E 6F 74 65 20 66 6F 72 20 57 69 6E 64 6F 77 73 20 31 30 0A 19 50 68 61 6E 74 6F 6D 20 50 72 69 6E 74 20 74 6F 20 45 76 65 72 6E 6F 74 65 0A 11 4F 6E 65 4E 6F 74 65 20 28 44 65 73 6B 74 6F 70 29 0A 1D 4D 69 63 72 6F 73 6F 66 74 20 58 50 53 20 44 6F 63 75 6D 65 6E 74 20 57 72 69 74 65 72 0A 16 4D 69 63 72 6F 73 6F 66 74 20 50 72 69 6E 74 20 74 6F 20 50 44 46 0A 15 46 6F 78 69 74 20 50 68 61 6E 74 6F 6D 20 50 72 69 6E 74 65 72 0A 03 46 61 78 32 09 0A 03 6A 70 67 10 01 18 00 32 0A 0A 04 6A 70 65 67 10 01 18 00 32 09 0A 03 70 6E 67 10 01 18 00 32 09 0A 03 67 69 66 10 01 18 00 32 09 0A 03 62 6D 70 10 01 18 00 32 09 0A 03 64 6F 63 10 01 18 01 32 0A 0A 04 64 6F 63 78 10 01 18 01 32 09 0A 03 74 78 74 10 00 18 00 32 09 0A 03 70 64 66 10 01 18 01 32 09 0A 03 70 70 74 10 01 18 01 32 0A 0A 04 70 70 74 78 10 01 18 01 32 09 0A 03 78 6C 73 10 01 18 01 32 0A 0A 04 78 6C 73 78 10 01 18 01
|
|
|
+msgSeq=0x00001AFF(6911)
|
|
|
+msgSubtype=0x00000009(9)
|
|
|
+msgTime=0x5FDF21A3(1608458659)
|
|
|
+msgType=0x00000211(529)
|
|
|
+msgUid=0x010000005FDEE04C(72057595646369868)
|
|
|
+realMsgTime=0x5FDF21A3(1608458659)
|
|
|
+svrIp=0x3E689409(1047041033)
|
|
|
+toUin=0x0000000026BA1173(649728371)
|
|
|
+}
|
|
|
+ */
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw contextualBugReportException(
|
|
|
+ "解析 OnlinePush.PbPushTransMsg, msgType=${data.msgType}",
|
|
|
+ data._miraiContentToString(),
|
|
|
+ null,
|
|
|
+ "并描述此时机器人是否被踢出, 或是否有成员列表变更等动作."
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun PipelineContext.handleLeave(
|
|
|
+ target: Long,
|
|
|
+ kind: Int,
|
|
|
+ operator: Long,
|
|
|
+ groupUin: Long
|
|
|
+ ) {
|
|
|
+ when (kind) {
|
|
|
+ 2, 0x82 -> bot.getGroupByUin(groupUin)?.let { group ->
|
|
|
+ if (target == bot.id) {
|
|
|
+ collect(BotLeaveEvent.Active(group))
|
|
|
+ bot.groups.delegate.remove(group)
|
|
|
+ group.cancel(CancellationException("Left actively"))
|
|
|
+ } else {
|
|
|
+ val member = group[target] ?: return
|
|
|
+ collect(MemberLeaveEvent.Quit(member))
|
|
|
+ group.members.delegate.remove(member)
|
|
|
+ member.cancel(CancellationException("Left actively"))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 3, 0x83 -> bot.getGroupByUin(groupUin)?.let { group ->
|
|
|
+ if (target == bot.id) {
|
|
|
+ val member = group.members[operator] ?: return
|
|
|
+ collect(BotLeaveEvent.Kick(member))
|
|
|
+ bot.groups.delegate.remove(group)
|
|
|
+ group.cancel(CancellationException("Being kicked"))
|
|
|
+ } else {
|
|
|
+ val member = group[target] ?: return
|
|
|
+ collect(MemberLeaveEvent.Kick(member, group.members[operator]))
|
|
|
+ group.members.delegate.remove(member)
|
|
|
+ member.cancel(CancellationException("Being kicked"))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Group owner changes permission of a member, when bot is a member.
|
|
|
+ *
|
|
|
+ * @see BotGroupPermissionChangeEvent
|
|
|
+ * @see MemberPermissionChangeEvent
|
|
|
+ */
|
|
|
+ private fun PipelineContext.handlePermissionChange(
|
|
|
+ data: OnlinePushTrans.PbMsgInfo,
|
|
|
+ target: Long,
|
|
|
+ newPermissionByte: Int
|
|
|
+ ) {
|
|
|
+ val group = bot.getGroupByUin(data.fromUin) ?: return
|
|
|
+
|
|
|
+ val newPermission = if (newPermissionByte == 1) ADMINISTRATOR else MEMBER
|
|
|
+
|
|
|
+ if (target == bot.id) {
|
|
|
+ if (group.botPermission == newPermission) return
|
|
|
+
|
|
|
+ collect(BotGroupPermissionChangeEvent(group, group.botPermission, newPermission))
|
|
|
+ group.botAsMember.permission = newPermission
|
|
|
+ } else {
|
|
|
+ val member = group[target] ?: return
|
|
|
+ if (member.permission == newPermission) return
|
|
|
+
|
|
|
+ collect(MemberPermissionChangeEvent(member, member.permission, newPermission))
|
|
|
+ member.permission = newPermission
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Owner of the group [from] transfers ownership to another member [to], or retrieve ownership.
|
|
|
+ */
|
|
|
+ // TODO: 2021/6/26 tests
|
|
|
+ private suspend fun PipelineContext.handleGroupOwnershipTransfer(
|
|
|
+ data: OnlinePushTrans.PbMsgInfo,
|
|
|
+ from: Long,
|
|
|
+ to: Long,
|
|
|
+ ) {
|
|
|
+ val group = bot.getGroupByUin(data.fromUin)
|
|
|
+ if (from == bot.id) {
|
|
|
+ // bot -> member
|
|
|
+ group ?: return markAsConsumed()
|
|
|
+
|
|
|
+ // Bot permission changed to MEMBER
|
|
|
+ if (group.botPermission != MEMBER) {
|
|
|
+ collect(BotGroupPermissionChangeEvent(group, group.botPermission, MEMBER))
|
|
|
+ group.botAsMember.permission = MEMBER
|
|
|
+ }
|
|
|
+
|
|
|
+ // member Retrieve or permission changed to OWNER
|
|
|
+ var newOwner = group[to]
|
|
|
+ if (newOwner == null) {
|
|
|
+ newOwner = group.addNewNormalMember(MemberInfoImpl(uin = to, nick = "", permission = OWNER))
|
|
|
+ collect(MemberJoinEvent.Retrieve(newOwner))
|
|
|
+ } else if (newOwner.permission != OWNER) {
|
|
|
+ collect(MemberPermissionChangeEvent(newOwner, newOwner.permission, OWNER))
|
|
|
+ newOwner.permission = OWNER
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // member -> bot
|
|
|
+
|
|
|
+ // bot Retrieve or permission changed to OWNER
|
|
|
+ if (group == null) {
|
|
|
+ collect(BotJoinGroupEvent.Retrieve(bot.createGroupForBot(data.fromUin)!!))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // member permission changed to MEMBER
|
|
|
+ val member = group[from]
|
|
|
+ if (member != null && member.permission != MEMBER) {
|
|
|
+ collect(MemberPermissionChangeEvent(member, member.permission, MEMBER))
|
|
|
+ member.permission = MEMBER
|
|
|
+ } else {
|
|
|
+ // if member is null, he has already quit the group in another event.
|
|
|
+ }
|
|
|
+
|
|
|
+ if (group.botPermission != OWNER) {
|
|
|
+ collect(BotGroupPermissionChangeEvent(group, group.botPermission, OWNER))
|
|
|
+ group.botAsMember.permission = OWNER
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|