mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-09 18:00:33 +08:00
Group: new design
This commit is contained in:
parent
0c49d8c923
commit
b5efba2949
@ -7,7 +7,7 @@ import kotlinx.coroutines.sync.Mutex
|
|||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import net.mamoe.mirai.Bot.ContactSystem
|
import net.mamoe.mirai.Bot.ContactSystem
|
||||||
import net.mamoe.mirai.contact.*
|
import net.mamoe.mirai.contact.*
|
||||||
import net.mamoe.mirai.contact.internal.GroupImpl
|
import net.mamoe.mirai.contact.internal.Group
|
||||||
import net.mamoe.mirai.contact.internal.QQImpl
|
import net.mamoe.mirai.contact.internal.QQImpl
|
||||||
import net.mamoe.mirai.network.BotNetworkHandler
|
import net.mamoe.mirai.network.BotNetworkHandler
|
||||||
import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
|
import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
|
||||||
@ -139,7 +139,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) : CoroutineScope {
|
|||||||
suspend fun getGroup(id: GroupId): Group = id.value.let {
|
suspend fun getGroup(id: GroupId): Group = id.value.let {
|
||||||
if (_groups.containsKey(it)) _groups[it]!!
|
if (_groups.containsKey(it)) _groups[it]!!
|
||||||
else groupsLock.withLock {
|
else groupsLock.withLock {
|
||||||
_groups.getOrPut(it) { GroupImpl(bot, id) }
|
_groups.getOrPut(it) { Group(bot, id) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +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.network.protocol.tim.packet.action.QuitGroupResponse
|
||||||
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
|
||||||
|
|
||||||
@ -16,35 +16,65 @@ import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
|
|||||||
* - Group ID([Group.internalId]) 是与调用 API 时使用的 id.(在 QQ 客户端中不可见)
|
* - Group ID([Group.internalId]) 是与调用 API 时使用的 id.(在 QQ 客户端中不可见)
|
||||||
* @author Him188moe
|
* @author Him188moe
|
||||||
*/
|
*/
|
||||||
interface Group : Contact {
|
interface Group : Contact, Iterable<Member> {
|
||||||
|
/**
|
||||||
|
* 内部 ID. 内部 ID 为 [GroupId] 的映射
|
||||||
|
*/
|
||||||
val internalId: GroupInternalId
|
val internalId: GroupInternalId
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [Group] 实例创建的时候查询一次. 收到各事件后
|
* 群主 (同步事件更新)
|
||||||
|
* 进行 [updateGroupInfo] 时将会更新这个值.
|
||||||
*/
|
*/
|
||||||
val member: ContactList<Member>
|
val owner: Member
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 群名称 (同步事件更新)
|
||||||
|
* 进行 [updateGroupInfo] 时将会更新这个值.
|
||||||
|
*/
|
||||||
|
val name: String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入群公告, 没有时为空字符串. (同步事件更新)
|
||||||
|
* 进行 [updateGroupInfo] 时将会更新这个值.
|
||||||
|
*/
|
||||||
|
val announcement: String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
|
||||||
|
*
|
||||||
|
* **注意**: 获得的列表仅为这一时刻的成员列表的镜像. 它将不会被更新
|
||||||
|
*/
|
||||||
|
val members: ContactList<Member>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群成员. 若此 ID 的成员不存在, 则会抛出 [kotlin.NoSuchElementException]
|
||||||
|
*/
|
||||||
suspend fun getMember(id: UInt): Member
|
suspend fun getMember(id: UInt): Member
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询群资料
|
* 更新群资料. 群资料会与服务器事件同步事件更新, 一般情况下不需要手动更新.
|
||||||
*/ // should be `suspend val` if kotlin supports in the future
|
*
|
||||||
suspend fun queryGroupInfo(): GroupInfo
|
* @return 这一时刻的群资料
|
||||||
|
*/
|
||||||
|
suspend fun updateGroupInfo(): GroupInfo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
|
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
|
||||||
*
|
*
|
||||||
* @see QuiteGroupResponse.isSuccess 判断是否成功
|
* @see QuitGroupResponse.isSuccess 判断是否成功
|
||||||
*/
|
*/
|
||||||
suspend fun quite(): QuiteGroupResponse
|
suspend fun quit(): QuitGroupResponse
|
||||||
|
|
||||||
|
fun toFullString(): String = "Group(id=${this.id}, name=$name, owner=${owner.id}, members=${members.idContentString})"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一般的用户可见的 ID.
|
* 一般的用户可见的 ID.
|
||||||
* 在 TIM/QQ 客户端中所看到的的号码均是这个 ID.
|
* 在 TIM/QQ 客户端中所看到的的号码均是这个 ID.
|
||||||
*
|
*
|
||||||
* 注: 在引用群 ID 时, 应使用 [GroupId] 或 [GroupInternalId] 类型, 而不是 [UInt]
|
* 注: 在引用群 ID 时, 只应使用 [GroupId] 或 [GroupInternalId] 类型 (内联类无性能损失), 而不能使用 [UInt].
|
||||||
*
|
*
|
||||||
* @see GroupInternalId.toId 由 [GroupInternalId] 转换为 [GroupId]
|
* @see GroupInternalId.toId 由 [GroupInternalId] 转换为 [GroupId]
|
||||||
* @see GroupId.toInternalId 由 [GroupId] 转换为 [GroupInternalId]
|
* @see GroupId.toInternalId 由 [GroupId] 转换为 [GroupInternalId]
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.contact.internal
|
package net.mamoe.mirai.contact.internal
|
||||||
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.contact.*
|
import net.mamoe.mirai.contact.*
|
||||||
import net.mamoe.mirai.contact.data.Profile
|
import net.mamoe.mirai.contact.data.Profile
|
||||||
@ -26,32 +25,50 @@ internal sealed class ContactImpl : Contact {
|
|||||||
override suspend fun sendMessage(message: Message) = sendMessage(message.chain())
|
override suspend fun sendMessage(message: Message) = sendMessage(message.chain())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 [Group]
|
||||||
|
*/
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@PublishedApi
|
||||||
|
internal suspend fun Group(bot: Bot, groupId: GroupId): Group {
|
||||||
|
val info: RawGroupInfo = try {
|
||||||
|
bot.withSession { GroupPacket.QueryGroupInfo(qqAccount, groupId.toInternalId(), sessionKey).sendAndExpect() }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
error("Cannot obtain group info for id ${groupId.value}")
|
||||||
|
}
|
||||||
|
return GroupImpl(bot, groupId).apply { this.info = info.parseBy(this) }
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate", "CanBeParameter")
|
@Suppress("MemberVisibilityCanBePrivate", "CanBeParameter")
|
||||||
internal data class GroupImpl internal constructor(override val bot: Bot, val groupId: GroupId) : ContactImpl(), Group {
|
internal data class GroupImpl internal constructor(override val bot: Bot, val groupId: GroupId) : ContactImpl(), Group {
|
||||||
override val id: UInt get() = groupId.value
|
override val id: UInt get() = groupId.value
|
||||||
override val internalId = GroupId(id).toInternalId()
|
override val internalId = GroupId(id).toInternalId()
|
||||||
|
|
||||||
private val _members: MutableContactList<Member> = MutableContactList()
|
internal lateinit var info: GroupInfo
|
||||||
override val member: ContactList<Member> = ContactList(_members)
|
override val owner: Member get() = info.owner
|
||||||
private val membersLock: Mutex = Mutex()
|
override val name: String get() = info.name
|
||||||
|
override val announcement: String get() = info.announcement
|
||||||
|
override val members: ContactList<Member> get() = info.members
|
||||||
|
|
||||||
override suspend fun getMember(id: UInt): Member =
|
override suspend fun getMember(id: UInt): Member =
|
||||||
if (_members.containsKey(id)) _members[id]!!
|
if (members.containsKey(id)) members[id]!!
|
||||||
else throw NoSuchElementException("No such member whose id is $id in group $id")
|
else throw NoSuchElementException("No such member whose id is $id in group $id")
|
||||||
|
|
||||||
override suspend fun sendMessage(message: MessageChain) {
|
override suspend fun sendMessage(message: MessageChain) {
|
||||||
bot.sendPacket(GroupPacket.Message(bot.qqAccount, internalId, bot.sessionKey, message))
|
bot.sendPacket(GroupPacket.Message(bot.qqAccount, internalId, bot.sessionKey, message))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun queryGroupInfo(): GroupInfo = bot.withSession {
|
override suspend fun updateGroupInfo(): GroupInfo = bot.withSession {
|
||||||
GroupPacket.QueryGroupInfo(qqAccount, internalId, sessionKey).sendAndExpect()
|
GroupPacket.QueryGroupInfo(qqAccount, internalId, sessionKey).sendAndExpect<RawGroupInfo>().parseBy(this@GroupImpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun quite(): QuiteGroupResponse = bot.withSession {
|
override suspend fun quit(): QuitGroupResponse = bot.withSession {
|
||||||
GroupPacket.QuiteGroup(qqAccount, sessionKey, internalId).sendAndExpect()
|
GroupPacket.QuitGroup(qqAccount, sessionKey, internalId).sendAndExpect()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "Group(${this.id})"
|
override fun toString(): String = "Group(${this.id})"
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<Member> = members.delegate.values.iterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class QQImpl internal constructor(override val bot: Bot, override val id: UInt) : ContactImpl(), QQ {
|
internal data class QQImpl internal constructor(override val bot: Bot, override val id: UInt) : ContactImpl(), QQ {
|
||||||
@ -76,6 +93,7 @@ internal data class QQImpl internal constructor(override val bot: Bot, override
|
|||||||
/**
|
/**
|
||||||
* 群成员
|
* 群成员
|
||||||
*/
|
*/
|
||||||
|
@PublishedApi
|
||||||
internal data class MemberImpl(private val delegate: QQ, override val group: Group, override val permission: MemberPermission) : QQ by delegate, Member {
|
internal data class MemberImpl(private val delegate: QQ, override val group: Group, override val permission: MemberPermission) : QQ by delegate, Member {
|
||||||
override fun toString(): String = "Member(id=${this.id}, permission=$permission)"
|
override fun toString(): String = "Member(id=${this.id}, permission=$permission)"
|
||||||
}
|
}
|
@ -5,8 +5,6 @@ package net.mamoe.mirai.message
|
|||||||
import net.mamoe.mirai.contact.Contact
|
import net.mamoe.mirai.contact.Contact
|
||||||
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendImagePacket
|
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendImagePacket
|
||||||
import net.mamoe.mirai.utils.ExternalImage
|
import net.mamoe.mirai.utils.ExternalImage
|
||||||
import net.mamoe.mirai.utils.io.debugPrintln
|
|
||||||
import net.mamoe.mirai.utils.io.toUHexString
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,7 +38,7 @@ class ImageId0x03 constructor(override inline val value: String, inline val uniq
|
|||||||
.replace("-", "")
|
.replace("-", "")
|
||||||
.chunked(2)
|
.chunked(2)
|
||||||
.map { (it[0] + it[1].toString()).toUByte(16).toByte() }
|
.map { (it[0] + it[1].toString()).toUByte(16).toByte() }
|
||||||
.toByteArray().also { check(it.size == 16); debugPrintln("image md5=" + it.toUHexString()); debugPrintln("imageId=$this") }
|
.toByteArray().also { check(it.size == 16) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||||
|
@ -161,7 +161,7 @@ abstract class BotSessionBase(
|
|||||||
|
|
||||||
|
|
||||||
inline val BotSession.isOpen: Boolean get() = socket.isOpen
|
inline val BotSession.isOpen: Boolean get() = socket.isOpen
|
||||||
inline val BotSession.qqAccount: UInt get() = bot.account.id
|
inline val BotSession.qqAccount: UInt get() = bot.account.id // 为了与群和好友的 id 区别.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取得 [BotNetworkHandler] 的 sessionKey.
|
* 取得 [BotNetworkHandler] 的 sessionKey.
|
||||||
|
@ -69,7 +69,7 @@ enum class KnownPacketId(override inline val value: UShort, override inline val
|
|||||||
inline HEARTBEAT(0x0058u, HeartbeatPacket),
|
inline HEARTBEAT(0x0058u, HeartbeatPacket),
|
||||||
inline S_KEY(0x001Du, RequestSKeyPacket),
|
inline S_KEY(0x001Du, RequestSKeyPacket),
|
||||||
inline ACCOUNT_INFO(0x005Cu, RequestAccountInfoPacket),
|
inline ACCOUNT_INFO(0x005Cu, RequestAccountInfoPacket),
|
||||||
inline SEND_GROUP_MESSAGE(0x0002u, GroupPacket),
|
inline GROUP_PACKET(0x0002u, GroupPacket),
|
||||||
inline SEND_FRIEND_MESSAGE(0x00CDu, SendFriendMessagePacket),
|
inline SEND_FRIEND_MESSAGE(0x00CDu, SendFriendMessagePacket),
|
||||||
inline CAN_ADD_FRIEND(0x00A7u, CanAddFriendPacket),
|
inline CAN_ADD_FRIEND(0x00A7u, CanAddFriendPacket),
|
||||||
inline ADD_FRIEND(0x00A8u, AddFriendPacket),
|
inline ADD_FRIEND(0x00A8u, AddFriendPacket),
|
||||||
|
@ -5,7 +5,6 @@ package net.mamoe.mirai.network.protocol.tim.packet.action
|
|||||||
import kotlinx.io.core.*
|
import kotlinx.io.core.*
|
||||||
import net.mamoe.mirai.contact.*
|
import net.mamoe.mirai.contact.*
|
||||||
import net.mamoe.mirai.contact.internal.MemberImpl
|
import net.mamoe.mirai.contact.internal.MemberImpl
|
||||||
import net.mamoe.mirai.getQQ
|
|
||||||
import net.mamoe.mirai.message.MessageChain
|
import net.mamoe.mirai.message.MessageChain
|
||||||
import net.mamoe.mirai.message.internal.toPacket
|
import net.mamoe.mirai.message.internal.toPacket
|
||||||
import net.mamoe.mirai.network.BotNetworkHandler
|
import net.mamoe.mirai.network.BotNetworkHandler
|
||||||
@ -18,18 +17,48 @@ import net.mamoe.mirai.withSession
|
|||||||
/**
|
/**
|
||||||
* 群资料
|
* 群资料
|
||||||
*/
|
*/
|
||||||
data class GroupInfo(
|
@Suppress("MemberVisibilityCanBePrivate") // 将来使用
|
||||||
val group: Group,
|
class GroupInfo(
|
||||||
val owner: Member,
|
internal var _group: Group,
|
||||||
|
internal var _owner: Member,
|
||||||
|
internal var _name: String,
|
||||||
|
internal var _announcement: String,
|
||||||
|
internal var _members: ContactList<Member>
|
||||||
|
) {
|
||||||
|
val group: Group get() = _group
|
||||||
|
val owner: Member get() = _owner
|
||||||
|
val name: String get() = _name
|
||||||
|
val announcement: String get() = _announcement
|
||||||
|
val members: ContactList<Member> get() = _members
|
||||||
|
|
||||||
|
override fun toString(): String = "GroupInfo(id=${group.id}, owner=$owner, name=$name, announcement=$announcement, members=${members.idContentString}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data class RawGroupInfo(
|
||||||
|
val group: UInt,
|
||||||
|
val owner: UInt,
|
||||||
val name: String,
|
val name: String,
|
||||||
val announcement: String,
|
val announcement: String,
|
||||||
val members: ContactList<Member>
|
/**
|
||||||
) : GroupPacket.GroupPacketResponse
|
* 不含群主
|
||||||
|
*/
|
||||||
|
val members: Map<UInt, MemberPermission>
|
||||||
|
) : GroupPacket.GroupPacketResponse {
|
||||||
|
suspend inline fun parseBy(group: Group): GroupInfo = group.bot.withSession {
|
||||||
|
GroupInfo(
|
||||||
|
group,
|
||||||
|
MemberImpl(this@RawGroupInfo.owner.qq(), group, MemberPermission.OWNER),
|
||||||
|
this@RawGroupInfo.name,
|
||||||
|
this@RawGroupInfo.announcement,
|
||||||
|
ContactList(this@RawGroupInfo.members.mapValuesTo(MutableContactList()) { MemberImpl(it.key.qq(), group, MemberPermission.OWNER) })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退出群的返回
|
* 退出群的返回
|
||||||
*/
|
*/
|
||||||
inline class QuiteGroupResponse(private val _group: GroupInternalId?) : Packet, GroupPacket.GroupPacketResponse {
|
inline class QuitGroupResponse(private val _group: GroupInternalId?) : Packet, GroupPacket.GroupPacketResponse {
|
||||||
val group: GroupInternalId get() = _group ?: error("request failed")
|
val group: GroupInternalId get() = _group ?: error("request failed")
|
||||||
val isSuccess: Boolean get() = _group != null
|
val isSuccess: Boolean get() = _group != null
|
||||||
|
|
||||||
@ -37,7 +66,7 @@ inline class QuiteGroupResponse(private val _group: GroupInternalId?) : Packet,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
@AnnotatedId(KnownPacketId.SEND_GROUP_MESSAGE)
|
@AnnotatedId(KnownPacketId.GROUP_PACKET)
|
||||||
object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
|
object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
|
||||||
@PacketVersion(date = "2019.10.19", timVersion = "2.3.2 (21173)")
|
@PacketVersion(date = "2019.10.19", timVersion = "2.3.2 (21173)")
|
||||||
fun Message(
|
fun Message(
|
||||||
@ -67,7 +96,7 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
|
|||||||
* 退出群
|
* 退出群
|
||||||
*/
|
*/
|
||||||
@PacketVersion(date = "2019.11.28", timVersion = "2.3.2 (21173)")
|
@PacketVersion(date = "2019.11.28", timVersion = "2.3.2 (21173)")
|
||||||
fun QuiteGroup(
|
fun QuitGroup(
|
||||||
bot: UInt,
|
bot: UInt,
|
||||||
sessionKey: SessionKey,
|
sessionKey: SessionKey,
|
||||||
group: GroupInternalId
|
group: GroupInternalId
|
||||||
@ -84,7 +113,7 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
|
|||||||
bot: UInt,
|
bot: UInt,
|
||||||
groupInternalId: GroupInternalId,
|
groupInternalId: GroupInternalId,
|
||||||
sessionKey: SessionKey
|
sessionKey: SessionKey
|
||||||
): OutgoingPacket = buildSessionPacket(bot, sessionKey, name = "QueryBulletin", headerSizeHint = 9) {
|
): OutgoingPacket = buildSessionPacket(bot, sessionKey, name = "QueryGroupInfo", headerSizeHint = 9) {
|
||||||
writeUByte(0x72u)
|
writeUByte(0x72u)
|
||||||
writeGroup(groupInternalId)
|
writeGroup(groupInternalId)
|
||||||
writeZero(4)
|
writeZero(4)
|
||||||
@ -105,19 +134,19 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
|
|||||||
|
|
||||||
0x09u -> {
|
0x09u -> {
|
||||||
if (readByte().toInt() == 0) {
|
if (readByte().toInt() == 0) {
|
||||||
QuiteGroupResponse(readUInt().groupInternalId())
|
QuitGroupResponse(readUInt().groupInternalId())
|
||||||
} else {
|
} else {
|
||||||
QuiteGroupResponse(null)
|
QuitGroupResponse(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
0x72u -> {
|
0x72u -> {
|
||||||
discardExact(1) // 00
|
discardExact(1) // 00
|
||||||
discardExact(4) // group internal id
|
discardExact(4) // group internal id
|
||||||
val group = readUInt().group() // group id
|
val group = readUInt() // group id
|
||||||
|
|
||||||
discardExact(13) //00 00 00 03 01 01 00 04 01 00 80 01 40
|
discardExact(13) //00 00 00 03 01 01 00 04 01 00 80 01 40
|
||||||
val owner = MemberImpl(readUInt().qq(), group, MemberPermission.OWNER)
|
val owner = readUInt()
|
||||||
discardExact(22)
|
discardExact(22)
|
||||||
val groupName = readUByteLVString()
|
val groupName = readUByteLVString()
|
||||||
|
|
||||||
@ -134,12 +163,11 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
|
|||||||
|
|
||||||
val stop = readUInt() // 标记读取群成员的结束
|
val stop = readUInt() // 标记读取群成员的结束
|
||||||
discardExact(1) // 00
|
discardExact(1) // 00
|
||||||
val members: MutableContactList<Member> = MutableContactList()
|
val members = mutableMapOf<UInt, MemberPermission>()
|
||||||
members[owner.id] = owner
|
|
||||||
do {
|
do {
|
||||||
val qq = readUInt()
|
val qq = readUInt()
|
||||||
val status = readUShort().toInt() // 这个群成员的状态, 最后一 bit 为管理员权限. 这里面还包含其他状态
|
val status = readUShort().toInt() // 这个群成员的状态, 最后一 bit 为管理员权限. 这里面还包含其他状态
|
||||||
if (qq == owner.id) {
|
if (qq == owner) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,9 +175,9 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
|
|||||||
1 -> MemberPermission.OPERATOR
|
1 -> MemberPermission.OPERATOR
|
||||||
else -> MemberPermission.MEMBER
|
else -> MemberPermission.MEMBER
|
||||||
}
|
}
|
||||||
members[qq] = MemberImpl(handler.bot.getQQ(qq), group, permission)
|
members[qq] = permission
|
||||||
} while (qq != stop && remaining != 0L)
|
} while (qq != stop && remaining != 0L)
|
||||||
return GroupInfo(group, owner, groupName, announcement, ContactList(members))
|
return RawGroupInfo(group, owner, groupName, announcement, members)
|
||||||
/*
|
/*
|
||||||
* 群 Mirai
|
* 群 Mirai
|
||||||
*
|
*
|
||||||
|
@ -93,7 +93,8 @@ object SubmitPasswordPacket : PacketFactory<SubmitPasswordPacket.LoginResponse,
|
|||||||
override fun toString(): String = "LoginResponse.CaptchaInit"
|
override fun toString(): String = "LoginResponse.CaptchaInit"
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Success(
|
@Suppress("unused")
|
||||||
|
class Success(
|
||||||
val sessionResponseDecryptionKey: SessionResponseDecryptionKey,
|
val sessionResponseDecryptionKey: SessionResponseDecryptionKey,
|
||||||
|
|
||||||
val token38: IoBuffer,//56
|
val token38: IoBuffer,//56
|
||||||
@ -103,7 +104,9 @@ object SubmitPasswordPacket : PacketFactory<SubmitPasswordPacket.LoginResponse,
|
|||||||
val nickname: String,
|
val nickname: String,
|
||||||
val age: Short,
|
val age: Short,
|
||||||
val gender: Gender
|
val gender: Gender
|
||||||
) : LoginResponse()
|
) : LoginResponse() {
|
||||||
|
override fun toString(): String = "LoginResponse.Success"
|
||||||
|
}
|
||||||
|
|
||||||
data class Failed(val result: LoginResult) : LoginResponse()
|
data class Failed(val result: LoginResult) : LoginResponse()
|
||||||
}
|
}
|
||||||
@ -222,6 +225,7 @@ inline class SessionResponseDecryptionKey(private val delegate: IoBuffer) : Decr
|
|||||||
override fun decrypt(input: ByteReadPacket): ByteReadPacket = input.decryptBy(delegate)
|
override fun decrypt(input: ByteReadPacket): ByteReadPacket = input.decryptBy(delegate)
|
||||||
|
|
||||||
override fun toString(): String = "SessionResponseDecryptionKey"
|
override fun toString(): String = "SessionResponseDecryptionKey"
|
||||||
|
|
||||||
companion object Type : DecrypterType<SessionResponseDecryptionKey>
|
companion object Type : DecrypterType<SessionResponseDecryptionKey>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,10 +59,12 @@ object RequestSessionPacket : PacketFactory<RequestSessionPacket.SessionKeyRespo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class SessionKeyResponse(
|
class SessionKeyResponse(
|
||||||
val sessionKey: SessionKey,
|
val sessionKey: SessionKey,
|
||||||
val tlv0105: ByteReadPacket? = null
|
val tlv0105: ByteReadPacket? = null
|
||||||
) : Packet
|
) : Packet {
|
||||||
|
override fun toString(): String = "SessionKeyResponse"
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): SessionKeyResponse {
|
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): SessionKeyResponse {
|
||||||
when (remaining) {
|
when (remaining) {
|
||||||
|
@ -46,33 +46,19 @@ object TouchPacket : PacketFactory<TouchPacket.TouchResponse, TouchKey>(TouchKey
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed class TouchResponse : Packet {
|
sealed class TouchResponse : Packet {
|
||||||
data class OK(
|
class OK(
|
||||||
var loginTime: Int,
|
var loginTime: Int,
|
||||||
val loginIP: String,
|
val loginIP: String,
|
||||||
val token0825: ByteArray
|
val token0825: ByteArray
|
||||||
) : TouchResponse() {
|
) : TouchResponse() {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun toString(): String = "TouchResponse.OK"
|
||||||
if (this === other) return true
|
|
||||||
if (other !is OK) return false
|
|
||||||
|
|
||||||
if (loginTime != other.loginTime) return false
|
|
||||||
if (loginIP != other.loginIP) return false
|
|
||||||
if (!token0825.contentEquals(other.token0825)) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
class Redirection(
|
||||||
var result = loginTime
|
|
||||||
result = 31 * result + loginIP.hashCode()
|
|
||||||
result = 31 * result + token0825.contentHashCode()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Redirection(
|
|
||||||
val serverIP: String? = null
|
val serverIP: String? = null
|
||||||
) : TouchResponse()
|
) : TouchResponse() {
|
||||||
|
override fun toString(): String = "TouchResponse.Redirection"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): TouchResponse {
|
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): TouchResponse {
|
||||||
|
Loading…
Reference in New Issue
Block a user