Support Group Retrieve, fix #528 (#531)

* Support Group Retrieve, fix #528

* Code Review

- Fix unexpected member in owner changing event.
- Allocate group when changing the owner to the bot if group is missing.
This commit is contained in:
Karlatemp 2020-09-15 19:30:52 +08:00 committed by GitHub
parent 8d0fd96a22
commit 359c9cdc5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 172 additions and 52 deletions

View File

@ -137,6 +137,17 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
}
}
suspend fun QQAndroidBot.createGroupForBot(groupUin: Long): Group? {
val group = getGroupByUinOrNull(groupUin)
if (group != null) {
return null
}
return getNewGroup(Group.calculateGroupCodeByGroupUin(groupUin))?.apply {
groups.delegate.addLast(this)
}
}
@OptIn(FlowPreview::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
// 00 00 01 0F 08 00 12 00 1A 34 08 FF C1 C4 F1 05 10 FF C1 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 8A CA 91 D1 0C 48 9B A5 BD 9B 0A 58 DE 9D 99 F8 08 60 1D 68 FF C1 C4 F1 05 70 00 20 02 2A 9D 01 08 F3 C1 C4 F1 05 10 A2 FF 8C F0 03 18 01 22 8A 01 0A 2A 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 A6 01 20 0B 28 AE F9 01 30 F4 C1 C4 F1 05 38 A7 E3 D8 D4 84 80 80 80 01 B8 01 CD B5 01 12 08 08 01 10 00 18 00 20 00 1A 52 0A 50 0A 27 08 00 10 F4 C1 C4 F1 05 18 A7 E3 D8 D4 04 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 08 0A 06 0A 04 4E 4D 53 4C 12 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 12 04 4A 02 08 00 30 01 2A 15 08 97 A2 C1 F1 05 10 95 A6 F5 E5 0C 18 01 30 01 40 01 48 81 01 2A 10 08 D3 F7 B5 F1 05 10 DD F1 92 B7 07 18 01 30 01 38 00 42 00 48 00
@ -198,23 +209,12 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
msgQueueMutex.unlock()
msgUidQueue.addLast(msgUid)
suspend fun createGroupForBot(groupUin: Long): Group? {
val group = bot.getGroupByUinOrNull(groupUin)
if (group != null) {
return null
}
return bot.getNewGroup(Group.calculateGroupCodeByGroupUin(groupUin))?.apply {
bot.groups.delegate.addLast(this)
}
}
when (msg.msgHead.msgType) {
33 -> bot.groupListModifyLock.withLock {
if (msg.msgHead.authUin == bot.id) {
// 邀请入群
return@mapNotNull createGroupForBot(msg.msgHead.fromUin)?.let {
return@mapNotNull bot.createGroupForBot(msg.msgHead.fromUin)?.let {
// 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
val invitorUin = msg.msgBody.msgContent.sliceArray(10..13).toInt().toLong()
@ -256,7 +256,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
}
38 -> bot.groupListModifyLock.withLock { // 建群
return@mapNotNull createGroupForBot(msg.msgHead.fromUin)
return@mapNotNull bot.createGroupForBot(msg.msgHead.fromUin)
?.let { BotJoinGroupEvent.Active(it) }
}
@ -265,7 +265,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
// msg.msgHead.authUin: 处理人
return@mapNotNull if (msg.msgHead.toUin == bot.id) {
createGroupForBot(msg.msgHead.fromUin)
bot.createGroupForBot(msg.msgHead.fromUin)
?.let { BotJoinGroupEvent.Active(it) }
} else {
null

View File

@ -20,14 +20,14 @@ import kotlinx.io.core.readUByte
import kotlinx.io.core.readUInt
import net.mamoe.mirai.JavaFriendlyAPI
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.event.events.BotGroupPermissionChangeEvent
import net.mamoe.mirai.event.events.MemberLeaveEvent
import net.mamoe.mirai.event.events.MemberPermissionChangeEvent
import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.contact.GroupImpl
import net.mamoe.mirai.qqandroid.contact.MemberImpl
import net.mamoe.mirai.qqandroid.contact.checkIsMemberImpl
import net.mamoe.mirai.qqandroid.message.contextualBugReportException
import net.mamoe.mirai.qqandroid.network.MultiPacketByIterable
import net.mamoe.mirai.qqandroid.network.Packet
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.OnlinePushTrans
import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory
@ -45,52 +45,149 @@ internal object OnlinePushPbPushTransMsg :
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {
val content = this.readProtoBuf(OnlinePushTrans.PbMsgInfo.serializer())
if (!bot.client.pbPushTransMsgCacheList.ensureNoDuplication(content.msgSeq)) {
return null
}
// bot.network.logger.debug { content._miraiContentToString() }
content.msgData.read<Unit> {
when (content.msgType) {
44 -> {
// 3D C4 33 DD 01 FF CD 76 F4 03 C3 7E 2E 34
// 群转让
// start with 3D C4 33 DD 01 FF
// 3D C4 33 DD 01 FF C3 7E 2E 34 CD 76 F4 03
// 权限变更
// 3D C4 33 DD 01 00/01 .....
// 3D C4 33 DD 01 01 C3 7E 2E 34 01
this.discardExact(5)
val var4 = readByte().toInt()
var var5 = 0L
val target = readUInt().toLong()
if (var4 != 0 && var4 != 1) {
var5 = readUInt().toLong()
}
val group = bot.getGroupByUin(content.fromUin) as GroupImpl
if (var5 == 0L && this.remaining == 1L) {//管理员变更
val newPermission =
if (this.readByte().toInt() == 1) MemberPermission.ADMINISTRATOR
else MemberPermission.MEMBER
if (target == bot.id) {
if (group.botPermission == newPermission) {
return null
when (val mode = readUByte().toInt()) {
0xFF -> {
// 群转让 / huifu.qq.com
// From -> to
val from = readUInt().toLong()
val to = readUInt().toLong()
val results = ArrayList<Packet>()
// println("$from -> $to")
if (to == bot.id) {
if (bot.getGroupByUinOrNull(content.fromUin) == null) {
MessageSvcPbGetMsg.run {
results.add(BotJoinGroupEvent.Retrieve(
bot.createGroupForBot(content.fromUin)!!
))
}
}
}
val group = bot.getGroupByUin(content.fromUin) as GroupImpl
if (from == bot.id) {
if (group.botPermission != MemberPermission.MEMBER)
results.add(
BotGroupPermissionChangeEvent(
group, group.botPermission.also {
group.botAsMember.checkIsMemberImpl().permission =
MemberPermission.MEMBER
},
MemberPermission.MEMBER
)
)
} else {
val member = group[from] as MemberImpl
if (member.permission != MemberPermission.MEMBER) {
results.add(
MemberPermissionChangeEvent(
member,
member.permission.also { member.permission = MemberPermission.MEMBER },
MemberPermission.MEMBER
)
)
}
}
if (to == bot.id) {
if (group.botPermission != MemberPermission.OWNER) {
results.add(
BotGroupPermissionChangeEvent(
group,
group.botAsMember.permission.also {
group.botAsMember.checkIsMemberImpl().permission =
MemberPermission.OWNER
},
MemberPermission.OWNER
)
)
}
} else {
val newOwner = group.getOrNull(to) ?: group.newMember(object : MemberInfo {
override val nameCard: String
get() = ""
override val permission: MemberPermission
get() = MemberPermission.OWNER
override val specialTitle: String
get() = ""
override val muteTimestamp: Int
get() = 0
override val uin: Long
get() = to
override val nick: String
get() = ""
}).also { owner ->
owner.checkIsMemberImpl().permission = MemberPermission.OWNER
group.members.delegate.addLast(owner)
results.add(MemberJoinEvent.Retrieve(owner))
}
if (newOwner.permission != MemberPermission.OWNER) {
results.add(
MemberPermissionChangeEvent(
newOwner,
newOwner.permission.also {
newOwner.checkIsMemberImpl().permission = MemberPermission.OWNER
},
MemberPermission.OWNER
)
)
}
}
return MultiPacketByIterable(results)
}
else -> {
var var5 = 0L
val target = readUInt().toLong()
if (mode != 0 && mode != 1) {
var5 = readUInt().toLong()
}
return BotGroupPermissionChangeEvent(
group,
group.botPermission.also {
group.botAsMember.checkIsMemberImpl().permission = newPermission
},
newPermission
)
} else {
val member = group[target] as MemberImpl
if (member.permission == newPermission) {
return null
}
val group = bot.getGroupByUin(content.fromUin) as GroupImpl
return MemberPermissionChangeEvent(
member,
member.permission.also { member.permission = newPermission },
newPermission
)
if (var5 == 0L && this.remaining == 1L) {//管理员变更
val newPermission =
if (this.readByte().toInt() == 1) MemberPermission.ADMINISTRATOR
else MemberPermission.MEMBER
if (target == bot.id) {
if (group.botPermission == newPermission) {
return null
}
return BotGroupPermissionChangeEvent(
group,
group.botPermission.also {
group.botAsMember.checkIsMemberImpl().permission = newPermission
},
newPermission
)
} else {
val member = group[target] as MemberImpl
if (member.permission == newPermission) {
return null
}
return MemberPermissionChangeEvent(
member,
member.permission.also { member.permission = newPermission },
newPermission
)
}
}
}
}
}

View File

@ -24,6 +24,7 @@ import net.mamoe.mirai.event.BroadcastControllable
import net.mamoe.mirai.event.internal.MiraiAtomicBoolean
import net.mamoe.mirai.qqandroid.network.Packet
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.SinceMirai
import net.mamoe.mirai.utils.internal.runBlocking
import kotlin.internal.LowPriorityInOverloadResolution
import kotlin.jvm.*
@ -130,6 +131,17 @@ public sealed class BotJoinGroupEvent : GroupEvent, BotPassiveEvent, Packet, Abs
return "BotJoinGroupEvent.Invite(invitor=$invitor)"
}
}
/**
* 原群主通过 https://huifu.qq.com/ 恢复原来群主身份并入群,
* [Bot] 是原群主
*/
@MiraiExperimentalAPI
@SinceMirai("1.3.0")
public data class Retrieve internal constructor(
public override val group: Group
) : BotJoinGroupEvent() {
override fun toString(): String = "MemberJoinEvent.Retrieve(group=${group.id})"
}
}
// region 群设置
@ -260,6 +272,17 @@ public sealed class MemberJoinEvent(
) : MemberJoinEvent(member) {
public override fun toString(): String = "MemberJoinEvent.Active(member=${member.id})"
}
/**
* 原群主通过 https://huifu.qq.com/ 恢复原来群主身份并入群,
* 此时 [member] [Member.permission] 肯定是 [MemberPermission.OWNER]
*/
@SinceMirai("1.3.0")
public data class Retrieve internal constructor(
public override val member: Member
) : MemberJoinEvent(member) {
override fun toString(): String = "MemberJoinEvent.Retrieve(member=${member.id})"
}
}
/**