Commit 494b160a authored by Him188's avatar Him188

Add MemberQuitEvent, BeingKickEvent, QuiteGroup

parent 0f1e9a3d
...@@ -3,6 +3,7 @@ ...@@ -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 { ...@@ -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) ...@@ -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].
* *
......
...@@ -47,6 +47,10 @@ internal data class GroupImpl internal constructor(override val bot: Bot, val gr ...@@ -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})"
} }
......
package net.mamoe.mirai.network.protocol.tim.packet.action
class MemberKickEvent
//object MemberKickEventPacketFactory : SessionPacketFactory<
\ No newline at end of file
...@@ -26,9 +26,19 @@ data class GroupInfo( ...@@ -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>() { ...@@ -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>() { ...@@ -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>() { ...@@ -253,7 +285,6 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
*/ */
} }
0x2Au -> MessageResponse
else -> unsupported() else -> unsupported()
} }
} }
......
@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()))
}
}
\ No newline at end of file
...@@ -95,7 +95,7 @@ abstract class KnownEventParserAndHandler<TPacket : Packet>(override val id: USh ...@@ -95,7 +95,7 @@ abstract class KnownEventParserAndHandler<TPacket : Packet>(override val id: USh
GroupMessageEventParserAndHandler, GroupMessageEventParserAndHandler,
FriendMessageEventParserAndHandler, FriendMessageEventParserAndHandler,
FriendAddRequestEventPacket, FriendAddRequestEventPacket,
BeingKickEventPacketHandler, MemberGoneEventPacketHandler,
ConnectionOccupiedPacketFactory ConnectionOccupiedPacketFactory
) )
} }
\ No newline at end of file
...@@ -12,7 +12,7 @@ inline class IgnoredEventPacket(val id: UShort) : EventPacket { ...@@ -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()) }
}() }()
......
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
...@@ -3,20 +3,93 @@ ...@@ -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
/**
* 群成员列表变动事件.
*
* 可为成员增多, 或减少.
*/
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
/** /**
* 成员被踢 * 成员退出. 可能是被踢出也可能是主动退
*/ */
data class MemberKickEvent( @Suppress("EXPERIMENTAL_API_USAGE")
val member: Member object MemberGoneEventPacketHandler : KnownEventParserAndHandler<MemberListChangedEvent>(0x0022u) {
) : EventPacket override suspend fun ByteReadPacket.parse(bot: Bot, identity: EventPacketIdentity): MemberListChangedEvent {
discardExact(11)
object MemberKickEventPacketFactory : KnownEventParserAndHandler<MemberKickEvent>(0x0022u) {
override suspend fun ByteReadPacket.parse(bot: Bot, identity: EventPacketIdentity): MemberKickEvent { discardExact(1)
TODO() val group = bot.getGroup(readUInt())
// return MemberKickEvent()
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
} }
} }
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.network.protocol.tim.packet.event
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