From 494b160ade0408606e074a65091778e497d08d99 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 28 Nov 2019 21:21:08 +0800 Subject: [PATCH] Add MemberQuitEvent, BeingKickEvent, QuiteGroup --- .../kotlin/net.mamoe.mirai/contact/Group.kt | 14 +++ .../contact/internal/ContactImpl.kt | 4 + .../protocol/tim/packet/action/GroupMember.kt | 6 -- .../protocol/tim/packet/action/GroupPacket.kt | 37 +++++++- .../tim/packet/event/BeingKickEvent.kt | 37 -------- .../tim/packet/event/EventPacketFactory.kt | 2 +- .../protocol/tim/packet/event/Ignored.kt | 2 +- .../protocol/tim/packet/event/MemberJoin.kt | 7 ++ .../tim/packet/event/MemberKickEvent.kt | 93 +++++++++++++++++-- .../protocol/tim/packet/event/MuteEvent.kt | 4 + .../protocol/tim/packet/event/QuitGroup.kt | 4 + 11 files changed, 152 insertions(+), 58 deletions(-) delete mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupMember.kt delete mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/BeingKickEvent.kt create mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberJoin.kt create mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MuteEvent.kt create mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/QuitGroup.kt diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt index bd3fbdef0..c431b3cb7 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt @@ -3,6 +3,7 @@ package net.mamoe.mirai.contact import net.mamoe.mirai.network.protocol.tim.packet.action.GroupInfo +import net.mamoe.mirai.network.protocol.tim.packet.action.QuiteGroupResponse import net.mamoe.mirai.utils.internal.PositiveNumbers import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail @@ -30,6 +31,13 @@ interface Group : Contact { * 查询群资料 */ // should be `suspend val` if kotlin supports in the future suspend fun queryGroupInfo(): GroupInfo + + /** + * 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败 + * + * @see QuiteGroupResponse.isSuccess 判断是否成功 + */ + suspend fun quite(): QuiteGroupResponse } /** @@ -49,6 +57,12 @@ inline class GroupId(inline val value: UInt) @Suppress("NOTHING_TO_INLINE") inline fun UInt.groupId(): GroupId = GroupId(this) +/** + * 将 [this] 转为 [GroupInternalId]. + */ +@Suppress("NOTHING_TO_INLINE") +inline fun UInt.groupInternalId(): GroupInternalId = GroupInternalId(this) + /** * 将无符号整数格式的 [Long] 转为 [GroupId]. * diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt index 888ff9d8d..0088813ed 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt @@ -47,6 +47,10 @@ internal data class GroupImpl internal constructor(override val bot: Bot, val gr GroupPacket.QueryGroupInfo(qqAccount, internalId, sessionKey).sendAndExpect() } + override suspend fun quite(): QuiteGroupResponse = bot.withSession { + GroupPacket.QuiteGroup(qqAccount, sessionKey, internalId).sendAndExpect() + } + override fun toString(): String = "Group(${this.id})" } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupMember.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupMember.kt deleted file mode 100644 index 3e1e78192..000000000 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupMember.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.mamoe.mirai.network.protocol.tim.packet.action - - -class MemberKickEvent - -//object MemberKickEventPacketFactory : SessionPacketFactory< \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupPacket.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupPacket.kt index 3e858ab5d..8aefd76fa 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupPacket.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupPacket.kt @@ -26,9 +26,19 @@ data class GroupInfo( val members: ContactList ) : GroupPacket.GroupPacketResponse +/** + * 退出群的返回 + */ +inline class QuiteGroupResponse(private val _group: GroupInternalId?) : Packet, GroupPacket.GroupPacketResponse { + val group: GroupInternalId get() = _group ?: error("request failed") + val isSuccess: Boolean get() = _group != null + + override fun toString(): String = "GroupPacket.QuitResponse" +} + +@Suppress("FunctionName") @AnnotatedId(KnownPacketId.SEND_GROUP_MESSAGE) object GroupPacket : SessionPacketFactory() { - @Suppress("FunctionName") @PacketVersion(date = "2019.10.19", timVersion = "2.3.2 (21173)") fun Message( bot: UInt, @@ -53,10 +63,22 @@ object GroupPacket : SessionPacketFactory() { } } + /** + * 退出群 + */ + @PacketVersion(date = "2019.11.28", timVersion = "2.3.2 (21173)") + fun QuiteGroup( + bot: UInt, + sessionKey: SessionKey, + group: GroupInternalId + ): OutgoingPacket = buildSessionPacket(bot, sessionKey) { + writeUByte(0x09u) + writeGroup(group) + } + /** * 查询群信息 */ - @Suppress("FunctionName") @PacketVersion(date = "2019.11.27", timVersion = "2.3.2 (21173)") fun QueryGroupInfo( bot: UInt, @@ -79,6 +101,16 @@ object GroupPacket : SessionPacketFactory() { @UseExperimental(ExperimentalStdlibApi::class) override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): GroupPacketResponse = handler.bot.withSession { return when (readUByte().toUInt()) { + 0x2Au -> MessageResponse + + 0x09u -> { + if (readByte().toInt() == 0) { + QuiteGroupResponse(readUInt().groupInternalId()) + } else { + QuiteGroupResponse(null) + } + } + 0x72u -> { discardExact(1) // 00 discardExact(4) // group internal id @@ -253,7 +285,6 @@ object GroupPacket : SessionPacketFactory() { */ } - 0x2Au -> MessageResponse else -> unsupported() } } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/BeingKickEvent.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/BeingKickEvent.kt deleted file mode 100644 index 29b19687b..000000000 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/BeingKickEvent.kt +++ /dev/null @@ -1,37 +0,0 @@ -@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE") - -package net.mamoe.mirai.network.protocol.tim.packet.event - -import kotlinx.io.core.ByteReadPacket -import kotlinx.io.core.discardExact -import kotlinx.io.core.readUInt -import net.mamoe.mirai.Bot -import net.mamoe.mirai.contact.Group -import net.mamoe.mirai.contact.Member -import net.mamoe.mirai.getGroup -import net.mamoe.mirai.network.protocol.tim.packet.PacketVersion - -/** - * 机器人账号被踢出群 - */ -data class BeingKickEvent(val group: Group, val operator: Member) : EventPacket - -/** - * 机器人被踢出去群 - */ -object BeingKickEventPacketHandler : KnownEventParserAndHandler(0x0022u) { - //00 00 00 08 00 0A 00 04 01 00 00 - // 00 36 DD C4 A0 - // 01 2D 5C 53 A6 - // 03 3E 03 3F A2 - // 06 B9 DC C0 ED D4 B1 - // - // 00 30 31 63 35 35 31 34 63 62 36 64 37 39 61 65 61 66 35 66 33 34 35 64 39 63 32 34 64 65 37 32 36 64 39 64 36 39 36 64 66 66 32 38 64 63 38 32 37 36 - - @PacketVersion(date = "2019.11.24", timVersion = "2.3.2 (21173)") - override suspend fun ByteReadPacket.parse(bot: Bot, identity: EventPacketIdentity): BeingKickEvent { - discardExact(11 + 5 + 5 + 1) - val group = bot.getGroup(identity.from) - return BeingKickEvent(group, group.getMember(readUInt())) - } -} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/EventPacketFactory.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/EventPacketFactory.kt index c6ba4188d..40377ee4b 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/EventPacketFactory.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/EventPacketFactory.kt @@ -95,7 +95,7 @@ abstract class KnownEventParserAndHandler(override val id: USh GroupMessageEventParserAndHandler, FriendMessageEventParserAndHandler, FriendAddRequestEventPacket, - BeingKickEventPacketHandler, + MemberGoneEventPacketHandler, ConnectionOccupiedPacketFactory ) } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Ignored.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Ignored.kt index 4754659a9..286f7fa5d 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Ignored.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Ignored.kt @@ -12,7 +12,7 @@ inline class IgnoredEventPacket(val id: UShort) : EventPacket { object IgnoredEventIds : List by { listOf( - 0x0021u, + //0x0021u, // 与群成员加入有关 0x0210u // 新朋友等字符串通知 ).map { IgnoredEventParserAndHandler(it.toUShort()) } }() diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberJoin.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberJoin.kt new file mode 100644 index 000000000..ebc0afe6b --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberJoin.kt @@ -0,0 +1,7 @@ +package net.mamoe.mirai.network.protocol.tim.packet.event + + +//群有新成员加入 +//事件 id 00 21 +// +//00 00 00 08 00 0A 00 04 01 00 00 00 32 DC FC C8 01 2D 5C 53 A6 03 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 42 34 37 31 30 36 43 30 44 44 34 41 34 44 30 35 30 39 44 45 31 32 30 42 43 35 45 34 44 38 45 42 37 30 36 39 31 45 36 44 45 36 44 39 46 37 36 30 \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberKickEvent.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberKickEvent.kt index 27520fca1..da78007ca 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberKickEvent.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberKickEvent.kt @@ -3,20 +3,93 @@ package net.mamoe.mirai.network.protocol.tim.packet.event import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.readUByte +import kotlinx.io.core.readUInt import net.mamoe.mirai.Bot +import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Member - +import net.mamoe.mirai.getGroup +import net.mamoe.mirai.qqAccount +import net.mamoe.mirai.utils.io.discardExact +import net.mamoe.mirai.utils.io.toUHexString +import net.mamoe.mirai.utils.io.unsupported /** - * 成员被踢出 + * 群成员列表变动事件. + * + * 可为成员增多, 或减少. */ -data class MemberKickEvent( - val member: Member -) : EventPacket +interface MemberListChangedEvent : EventPacket + +/** + * 成员主动离开群 + */ +data class MemberQuitEvent( + val member: Member, + private val _operator: Member? +) : MemberListChangedEvent { + val isKick: Boolean get() = _operator != null + + /** + * 被踢出时的操作人. 若是主动退出则为 `null` + */ + val operator: Member get() = _operator ?: error("The action is not a kick") +} + +/** + * 机器人被踢出 + */ +data class BeingKickEvent(val group: Group, val operator: Member) : MemberListChangedEvent + +/** + * 成员退出. 可能是被踢出也可能是主动退出 + */ +@Suppress("EXPERIMENTAL_API_USAGE") +object MemberGoneEventPacketHandler : KnownEventParserAndHandler(0x0022u) { + override suspend fun ByteReadPacket.parse(bot: Bot, identity: EventPacketIdentity): MemberListChangedEvent { + discardExact(11) + + discardExact(1) + val group = bot.getGroup(readUInt()) + + discardExact(1) + val id = readUInt() + if (id == bot.qqAccount) { + discardExact(1) + return BeingKickEvent(group, group.getMember(readUInt())) + } + + val member = group.getMember(id) + + return when (val type = readUByte().toInt()) { + 0x02 -> MemberQuitEvent(member, _operator = null) + 0x03 -> MemberQuitEvent(member, _operator = group.getMember(readUInt())) + else -> unsupported("Unsupported type " + type.toUHexString()) + } + + // 某群员主动离开, 群号 853343432 + // 00 00 00 08 00 0A 00 04 01 00 00 + // 00 (32 DC FC C8) + // 01 (2D 5C 53 A6) + // 02 + // 00 30 44 43 31 45 31 38 43 38 31 44 31 34 39 39 41 44 36 44 37 32 42 41 35 43 45 44 30 33 35 42 39 31 45 31 42 43 41 44 42 35 33 33 46 39 31 45 37 31 + + // 某群员被群主踢出, 群号 853343432 + // 00 00 00 08 00 0A 00 04 01 00 00 + // 00 (32 DC FC C8) + // 01 (2D 5C 53 A6) + // 03 (3E 03 3F A2) + // 06 B4 B4 BD A8 D5 DF + // 00 30 45 43 41 34 35 44 34 33 30 34 30 35 35 39 42 46 44 45 35 32 46 31 42 33 46 36 38 30 33 37 42 44 43 30 44 37 36 37 34 39 41 39 37 32 39 33 32 36 + + // 机器人被踢出 + // 00 00 00 08 00 0A 00 04 01 00 00 + // 00 (32 DC FC C8) + // 01 (2D 5C 53 A6) + // 03 (3E 03 3F A2) + // 06 B4 B4 BD A8 D5 DF + // 00 30 32 33 32 63 32 39 36 65 36 35 64 62 64 64 64 64 65 35 62 33 34 64 36 62 34 33 32 61 30 64 61 65 32 30 37 35 38 34 37 34 32 65 32 39 63 35 63 64 -object MemberKickEventPacketFactory : KnownEventParserAndHandler(0x0022u) { - override suspend fun ByteReadPacket.parse(bot: Bot, identity: EventPacketIdentity): MemberKickEvent { - TODO() - // return MemberKickEvent() } -} \ No newline at end of file +} + diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MuteEvent.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MuteEvent.kt new file mode 100644 index 000000000..0d5574712 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MuteEvent.kt @@ -0,0 +1,4 @@ +package net.mamoe.mirai.network.protocol.tim.packet.event + + + diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/QuitGroup.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/QuitGroup.kt new file mode 100644 index 000000000..1f961b55a --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/QuitGroup.kt @@ -0,0 +1,4 @@ +@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE") + +package net.mamoe.mirai.network.protocol.tim.packet.event +