Commit b75f90d5 authored by Him188's avatar Him188

Fix duplicated BotJoinGroupEvent,

Improve toString of Active, Kick events,
Cancel Group when kicked,
Fix #319
parent 2de767d4
...@@ -17,6 +17,7 @@ import io.ktor.client.request.forms.MultiPartFormDataContent ...@@ -17,6 +17,7 @@ import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.forms.formData import io.ktor.client.request.forms.formData
import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.UnstableDefault import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
...@@ -55,6 +56,7 @@ import net.mamoe.mirai.utils.* ...@@ -55,6 +56,7 @@ import net.mamoe.mirai.utils.*
import kotlin.collections.asSequence import kotlin.collections.asSequence
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmField
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.random.Random import kotlin.random.Random
...@@ -293,6 +295,8 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -293,6 +295,8 @@ internal abstract class QQAndroidBotBase constructor(
} }
override val groups: ContactList<Group> = ContactList(LockFreeLinkedList()) override val groups: ContactList<Group> = ContactList(LockFreeLinkedList())
@JvmField
val groupListModifyLock = Mutex()
// internally visible only // internally visible only
fun getGroupByUin(uin: Long): Group { fun getGroupByUin(uin: Long): Group {
......
...@@ -260,13 +260,13 @@ internal class Structmsg : ProtoBuf { ...@@ -260,13 +260,13 @@ internal class Structmsg : ProtoBuf {
@ProtoId(55) @JvmField val msgDetail: String = "", @ProtoId(55) @JvmField val msgDetail: String = "",
@ProtoId(57) @JvmField val groupExtFlag: Int = 0, @ProtoId(57) @JvmField val groupExtFlag: Int = 0,
@ProtoId(58) @JvmField val actorUinNick: String = "", @ProtoId(58) @JvmField val actorUinNick: String = "",
@ProtoId(59) @JvmField val picUrl: ByteArray = EMPTY_BYTE_ARRAY, @ProtoId(59) @JvmField val picUrl: String = "",
@ProtoId(60) @JvmField val cloneUinNick: String = "", @ProtoId(60) @JvmField val cloneUinNick: String = "",
@ProtoId(61) @JvmField val reqUinBusinessCard: ByteArray = EMPTY_BYTE_ARRAY, @ProtoId(61) @JvmField val reqUinBusinessCard: String = "",
@ProtoId(63) @JvmField val eimGroupIdName: ByteArray = EMPTY_BYTE_ARRAY, @ProtoId(63) @JvmField val eimGroupIdName: String = "",
@ProtoId(64) @JvmField val reqUinPreRemark: ByteArray = EMPTY_BYTE_ARRAY, @ProtoId(64) @JvmField val reqUinPreRemark: String = "",
@ProtoId(65) @JvmField val actionUinQqNick: ByteArray = EMPTY_BYTE_ARRAY, @ProtoId(65) @JvmField val actionUinQqNick: String = "",
@ProtoId(66) @JvmField val actionUinRemark: ByteArray = EMPTY_BYTE_ARRAY, @ProtoId(66) @JvmField val actionUinRemark: String = "",
@ProtoId(67) @JvmField val reqUinGender: Int = 0, @ProtoId(67) @JvmField val reqUinGender: Int = 0,
@ProtoId(68) @JvmField val reqUinAge: Int = 0, @ProtoId(68) @JvmField val reqUinAge: Int = 0,
@ProtoId(69) @JvmField val c2cInviteJoinGroupFlag: Int = 0, @ProtoId(69) @JvmField val c2cInviteJoinGroupFlag: Int = 0,
......
...@@ -15,14 +15,17 @@ import kotlinx.io.core.ByteReadPacket ...@@ -15,14 +15,17 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.event.events.BotInvitedJoinGroupRequestEvent import net.mamoe.mirai.event.events.BotInvitedJoinGroupRequestEvent
import net.mamoe.mirai.event.events.BotLeaveEvent
import net.mamoe.mirai.event.events.MemberJoinRequestEvent import net.mamoe.mirai.event.events.MemberJoinRequestEvent
import net.mamoe.mirai.event.events.NewFriendRequestEvent import net.mamoe.mirai.event.events.NewFriendRequestEvent
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.message.contextualBugReportException
import net.mamoe.mirai.qqandroid.network.Packet import net.mamoe.mirai.qqandroid.network.Packet
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Structmsg import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Structmsg
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.qqandroid.utils._miraiContentToString
import net.mamoe.mirai.qqandroid.utils.io.serialization.loadAs import net.mamoe.mirai.qqandroid.utils.io.serialization.loadAs
import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
...@@ -145,36 +148,42 @@ internal class NewContact { ...@@ -145,36 +148,42 @@ internal class NewContact {
readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer()).run { readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer()).run {
val struct = groupmsgs?.firstOrNull() val struct = groupmsgs?.firstOrNull()
return if (struct == null) null else { return if (struct == null) null else struct.msg?.run<Structmsg.SystemMsg, Packet> {
struct.msg?.run<Structmsg.SystemMsg, Packet> { //this.soutv("SystemMsg")
when (c2cInviteJoinGroupFlag) { when (subType) {
1 -> { 1 -> { //管理员邀请
// 被邀请入群 when (c2cInviteJoinGroupFlag) {
BotInvitedJoinGroupRequestEvent( 1 -> {
bot, // 被邀请入群
struct.msgSeq, BotInvitedJoinGroupRequestEvent(
actionUin, bot, struct.msgSeq, actionUin,
groupCode, groupCode, groupName, actionUinNick
groupName, )
actionUinNick }
) 0 -> {
} // 成员申请入群
0 -> { MemberJoinRequestEvent(
// 成员申请入群 bot, struct.msgSeq, msgAdditional,
MemberJoinRequestEvent( struct.reqUin, groupCode, groupName, reqUinNick
bot, )
struct.msgSeq, }
msgAdditional, else -> throw contextualBugReportException(
struct.reqUin, "parse SystemMsgNewGroup, subType=1",
groupCode, forDebug = this._miraiContentToString()
groupName,
reqUinNick
) )
} }
else -> throw IllegalStateException("Unknown c2cInviteJoinGroupFlag: $c2cInviteJoinGroupFlag in SystemMsgNewGroup packet")
} }
} as Packet // 没有 as Packet 垃圾 kotlin 会把类型推断为Any 5 -> {
} val group = bot.getGroup(groupCode)
val operator = group[actionUin]
BotLeaveEvent.Kick(operator)
}
else -> throw contextualBugReportException(
"parse SystemMsgNewGroup",
forDebug = this._miraiContentToString()
)
}
} as Packet // 没有 as Packet 垃圾 kotlin 会把类型推断为Any
} }
} }
......
...@@ -12,6 +12,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive ...@@ -12,6 +12,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import kotlinx.atomicfu.loop import kotlinx.atomicfu.loop
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.withLock
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
...@@ -45,7 +46,6 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf ...@@ -45,7 +46,6 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
import net.mamoe.mirai.qqandroid.utils.read import net.mamoe.mirai.qqandroid.utils.read
import net.mamoe.mirai.qqandroid.utils.soutv
import net.mamoe.mirai.qqandroid.utils.toUHexString import net.mamoe.mirai.qqandroid.utils.toUHexString
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.debug import net.mamoe.mirai.utils.debug
...@@ -181,8 +181,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re ...@@ -181,8 +181,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
.mapNotNull<MsgComm.Msg, Packet> { msg -> .mapNotNull<MsgComm.Msg, Packet> { msg ->
when (msg.msgHead.msgType) { when (msg.msgHead.msgType) {
33 -> { // 邀请入群 33 -> bot.groupListModifyLock.withLock { // 邀请入群
val group = bot.getGroupByUinOrNull(msg.msgHead.fromUin) val group = bot.getGroupByUinOrNull(msg.msgHead.fromUin)
if (msg.msgHead.authUin == bot.id) { if (msg.msgHead.authUin == bot.id) {
if (group != null) { if (group != null) {
...@@ -203,7 +202,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re ...@@ -203,7 +202,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
// 有人被邀请(经过同意后)加入 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 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 // 搜索到群, 直接加入 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
msg.msgBody.msgContent.soutv("33类型的content") // msg.msgBody.msgContent.soutv("33类型的content")
if (group.members.contains(msg.msgHead.authUin)) { if (group.members.contains(msg.msgHead.authUin)) {
return@mapNotNull null return@mapNotNull null
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.cancel
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
...@@ -397,6 +399,7 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf( ...@@ -397,6 +399,7 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
val uin = vProtobuf.loadAs(SubD4.serializer()).uin val uin = vProtobuf.loadAs(SubD4.serializer()).uin
val group = bot.getGroupByUinOrNull(uin) ?: bot.getGroupOrNull(uin) val group = bot.getGroupByUinOrNull(uin) ?: bot.getGroupOrNull(uin)
return@lambda528 if (group != null && bot.groups.delegate.remove(group)) { return@lambda528 if (group != null && bot.groups.delegate.remove(group)) {
group.cancel(CancellationException("Being kicked"))
sequenceOf(BotLeaveEvent.Active(group)) sequenceOf(BotLeaveEvent.Active(group))
} else emptySequence() } else emptySequence()
}, },
......
...@@ -37,12 +37,18 @@ sealed class BotLeaveEvent : BotEvent, Packet, AbstractEvent() { ...@@ -37,12 +37,18 @@ sealed class BotLeaveEvent : BotEvent, Packet, AbstractEvent() {
/** /**
* 机器人主动退出一个群. * 机器人主动退出一个群.
*/ */
data class Active(override val group: Group) : BotLeaveEvent() data class Active(override val group: Group) : BotLeaveEvent() {
override fun toString(): String = "BotLeaveEvent.Active(group=${group.id})"
}
/** /**
* 机器人被管理员或群主踢出群. 暂不支持获取操作人 * 机器人被管理员或群主踢出群.
*/ */
data class Kick(override val group: Group) : BotLeaveEvent() data class Kick internal constructor(override val operator: Member) : BotLeaveEvent(), GroupOperableEvent {
override val group: Group get() = operator.group
override val bot: Bot get() = super<BotLeaveEvent>.bot
override fun toString(): String = "BotLeaveEvent.Kick(group=${group.id},operator=${operator.id})"
}
override val bot: Bot get() = group.bot override val bot: Bot get() = group.bot
} }
...@@ -201,12 +207,16 @@ sealed class MemberJoinEvent(override val member: Member) : GroupMemberEvent, Bo ...@@ -201,12 +207,16 @@ sealed class MemberJoinEvent(override val member: Member) : GroupMemberEvent, Bo
/** /**
* 被邀请加入群 * 被邀请加入群
*/ */
data class Invite(override val member: Member) : MemberJoinEvent(member) data class Invite(override val member: Member) : MemberJoinEvent(member) {
override fun toString(): String = "MemberJoinEvent.Invite(member=${member.id})"
}
/** /**
* 成员主动加入群 * 成员主动加入群
*/ */
data class Active(override val member: Member) : MemberJoinEvent(member) data class Active(override val member: Member) : MemberJoinEvent(member) {
override fun toString(): String = "MemberJoinEvent.Active(member=${member.id})"
}
} }
/** /**
...@@ -223,18 +233,14 @@ sealed class MemberLeaveEvent : GroupMemberEvent, AbstractEvent() { ...@@ -223,18 +233,14 @@ sealed class MemberLeaveEvent : GroupMemberEvent, AbstractEvent() {
*/ */
override val operator: Member? override val operator: Member?
) : MemberLeaveEvent(), Packet, GroupOperableEvent { ) : MemberLeaveEvent(), Packet, GroupOperableEvent {
override fun toString(): String { override fun toString(): String = "MemberLeaveEvent.Kick(member=${member.id}, operator=${operator?.id})"
return "MemberLeaveEvent.Kick(member=$member, operator=$operator)"
}
} }
/** /**
* 成员主动离开 * 成员主动离开
*/ */
data class Quit(override val member: Member) : MemberLeaveEvent(), Packet { data class Quit(override val member: Member) : MemberLeaveEvent(), Packet {
override fun toString(): String { override fun toString(): String = "MemberLeaveEvent.Quit(member=${member.id})"
return "MemberLeaveEvent.Quit(member=$member)"
}
} }
} }
...@@ -259,7 +265,7 @@ data class BotInvitedJoinGroupRequestEvent internal constructor( ...@@ -259,7 +265,7 @@ data class BotInvitedJoinGroupRequestEvent internal constructor(
*/ */
val invitorNick: String val invitorNick: String
) : BotEvent, Packet, AbstractEvent() { ) : BotEvent, Packet, AbstractEvent() {
val invitor: Friend = this.bot.getFriend(invitorId) val invitor: Friend get() = this.bot.getFriend(invitorId)
@JvmField @JvmField
internal val responded: MiraiAtomicBoolean = MiraiAtomicBoolean(false) internal val responded: MiraiAtomicBoolean = MiraiAtomicBoolean(false)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment