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
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].
*

View File

@ -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})"
}

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>
) : 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<GroupPacket.GroupPacketResponse>() {
@Suppress("FunctionName")
@PacketVersion(date = "2019.10.19", timVersion = "2.3.2 (21173)")
fun Message(
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)")
fun QueryGroupInfo(
bot: UInt,
@ -79,6 +101,16 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
@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<GroupPacket.GroupPacketResponse>() {
*/
}
0x2Au -> MessageResponse
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,
FriendMessageEventParserAndHandler,
FriendAddRequestEventPacket,
BeingKickEventPacketHandler,
MemberGoneEventPacketHandler,
ConnectionOccupiedPacketFactory
)
}

View File

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