Add MemberQuitEvent, BeingKickEvent, QuiteGroup

This commit is contained in:
Him188 2019-11-28 21:21:08 +08:00
parent 0f1e9a3dd2
commit 494b160ade
11 changed files with 152 additions and 58 deletions

View File

@ -3,6 +3,7 @@
package net.mamoe.mirai.contact package net.mamoe.mirai.contact
import net.mamoe.mirai.network.protocol.tim.packet.action.GroupInfo 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.PositiveNumbers
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
@ -30,6 +31,13 @@ interface Group : Contact {
* 查询群资料 * 查询群资料
*/ // should be `suspend val` if kotlin supports in the future */ // should be `suspend val` if kotlin supports in the future
suspend fun queryGroupInfo(): GroupInfo 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") @Suppress("NOTHING_TO_INLINE")
inline fun UInt.groupId(): GroupId = GroupId(this) inline fun UInt.groupId(): GroupId = GroupId(this)
/**
* [this] 转为 [GroupInternalId].
*/
@Suppress("NOTHING_TO_INLINE")
inline fun UInt.groupInternalId(): GroupInternalId = GroupInternalId(this)
/** /**
* 将无符号整数格式的 [Long] 转为 [GroupId]. * 将无符号整数格式的 [Long] 转为 [GroupId].
* *

View File

@ -47,6 +47,10 @@ internal data class GroupImpl internal constructor(override val bot: Bot, val gr
GroupPacket.QueryGroupInfo(qqAccount, internalId, sessionKey).sendAndExpect() 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})" override fun toString(): String = "Group(${this.id})"
} }

View File

@ -1,6 +0,0 @@
package net.mamoe.mirai.network.protocol.tim.packet.action
class MemberKickEvent
//object MemberKickEventPacketFactory : SessionPacketFactory<

View File

@ -26,9 +26,19 @@ data class GroupInfo(
val members: ContactList<Member> val members: ContactList<Member>
) : GroupPacket.GroupPacketResponse ) : 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) @AnnotatedId(KnownPacketId.SEND_GROUP_MESSAGE)
object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() { object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
@Suppress("FunctionName")
@PacketVersion(date = "2019.10.19", timVersion = "2.3.2 (21173)") @PacketVersion(date = "2019.10.19", timVersion = "2.3.2 (21173)")
fun Message( fun Message(
bot: UInt, bot: UInt,
@ -53,10 +63,22 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
} }
} }
/**
* 退出群
*/
@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)") @PacketVersion(date = "2019.11.27", timVersion = "2.3.2 (21173)")
fun QueryGroupInfo( fun QueryGroupInfo(
bot: UInt, bot: UInt,
@ -79,6 +101,16 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
@UseExperimental(ExperimentalStdlibApi::class) @UseExperimental(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): GroupPacketResponse = handler.bot.withSession { override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): GroupPacketResponse = handler.bot.withSession {
return when (readUByte().toUInt()) { return when (readUByte().toUInt()) {
0x2Au -> MessageResponse
0x09u -> {
if (readByte().toInt() == 0) {
QuiteGroupResponse(readUInt().groupInternalId())
} else {
QuiteGroupResponse(null)
}
}
0x72u -> { 0x72u -> {
discardExact(1) // 00 discardExact(1) // 00
discardExact(4) // group internal id discardExact(4) // group internal id
@ -253,7 +285,6 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
*/ */
} }
0x2Au -> MessageResponse
else -> unsupported() else -> unsupported()
} }
} }

View File

@ -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<BeingKickEvent>(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()))
}
}

View File

@ -95,7 +95,7 @@ abstract class KnownEventParserAndHandler<TPacket : Packet>(override val id: USh
GroupMessageEventParserAndHandler, GroupMessageEventParserAndHandler,
FriendMessageEventParserAndHandler, FriendMessageEventParserAndHandler,
FriendAddRequestEventPacket, FriendAddRequestEventPacket,
BeingKickEventPacketHandler, MemberGoneEventPacketHandler,
ConnectionOccupiedPacketFactory ConnectionOccupiedPacketFactory
) )
} }

View File

@ -12,7 +12,7 @@ inline class IgnoredEventPacket(val id: UShort) : EventPacket {
object IgnoredEventIds : List<IgnoredEventParserAndHandler> by { object IgnoredEventIds : List<IgnoredEventParserAndHandler> by {
listOf( listOf(
0x0021u, //0x0021u, // 与群成员加入有关
0x0210u // 新朋友等字符串通知 0x0210u // 新朋友等字符串通知
).map { IgnoredEventParserAndHandler(it.toUShort()) } ).map { IgnoredEventParserAndHandler(it.toUShort()) }
}() }()

View File

@ -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

View File

@ -3,20 +3,93 @@
package net.mamoe.mirai.network.protocol.tim.packet.event package net.mamoe.mirai.network.protocol.tim.packet.event
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readUByte
import kotlinx.io.core.readUInt
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member 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( interface MemberListChangedEvent : EventPacket
val member: Member
) : 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<MemberListChangedEvent>(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<MemberKickEvent>(0x0022u) {
override suspend fun ByteReadPacket.parse(bot: Bot, identity: EventPacketIdentity): MemberKickEvent {
TODO()
// return MemberKickEvent()
} }
} }

View File

@ -0,0 +1,4 @@
package net.mamoe.mirai.network.protocol.tim.packet.event

View File

@ -0,0 +1,4 @@
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.network.protocol.tim.packet.event