mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-24 06:10:09 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
719023826d
@ -9,6 +9,7 @@ import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
internal abstract class ContactImpl : Contact
|
||||
|
||||
@ -73,18 +74,14 @@ internal class MemberImpl(
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal class GroupImpl(
|
||||
bot: QQAndroidBot, override val coroutineContext: CoroutineContext, override val id: Long
|
||||
bot: QQAndroidBot, override val coroutineContext: CoroutineContext,
|
||||
override val id: Long,
|
||||
override val groupCode: Long,
|
||||
override var name: String,
|
||||
override var announcement: String,
|
||||
override var members: ContactList<Member>
|
||||
) : ContactImpl(), Group {
|
||||
override lateinit var owner: Member
|
||||
override lateinit var name: String
|
||||
override lateinit var announcement: String
|
||||
override lateinit var members: ContactList<Member>
|
||||
|
||||
init {
|
||||
members = ContactList(LockFreeLinkedList())
|
||||
}
|
||||
|
||||
override val internalId: GroupInternalId = GroupId(id).toInternalId()
|
||||
|
||||
override fun getMember(id: Long): Member =
|
||||
members.delegate.filteringGetOrAdd(
|
||||
|
@ -12,6 +12,7 @@ import net.mamoe.mirai.utils.BotConfiguration
|
||||
import net.mamoe.mirai.utils.Context
|
||||
import net.mamoe.mirai.utils.LockFreeLinkedList
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.io.getRandomByteArray
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
@ -41,18 +42,13 @@ internal abstract class QQAndroidBotBase constructor(
|
||||
|
||||
override val groups: ContactList<Group> = ContactList(LockFreeLinkedList())
|
||||
|
||||
override suspend fun getGroup(id: GroupId): Group {
|
||||
return groups.delegate.filteringGetOrAdd({ it.id == id.value }, { GroupImpl(this as QQAndroidBot, coroutineContext, id.value) })
|
||||
override fun getGroupByID(id: Long): Group {
|
||||
return groups.delegate.getOrNull(id) ?: throw NoSuchElementException("Can not found group with ID=${id}")
|
||||
}
|
||||
|
||||
override suspend fun getGroup(internalId: GroupInternalId): Group {
|
||||
internalId.toId().value.let { id ->
|
||||
return groups.delegate.filteringGetOrAdd({ it.id == id }, { GroupImpl(this as QQAndroidBot, coroutineContext, id) })
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getGroup(id: Long): Group {
|
||||
return groups.delegate.filteringGetOrAdd({ it.id == id }, { GroupImpl(this as QQAndroidBot, coroutineContext, id) })
|
||||
override fun getGroupByGroupCode(groupCode: Long): Group {
|
||||
return groups.delegate.filterGetOrNull { it.groupCode == groupCode }
|
||||
?: throw NoSuchElementException("Can not found group with GroupCode=${groupCode}")
|
||||
}
|
||||
|
||||
override suspend fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult {
|
||||
|
@ -9,11 +9,15 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.Input
|
||||
import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.use
|
||||
import net.mamoe.mirai.contact.ContactList
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.data.MultiPacket
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.event.*
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.qqandroid.GroupImpl
|
||||
import net.mamoe.mirai.qqandroid.MemberImpl
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.QQImpl
|
||||
import net.mamoe.mirai.qqandroid.event.ForceOfflineEvent
|
||||
@ -149,28 +153,73 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
}
|
||||
|
||||
try {
|
||||
bot.logger.info("开始加载群组列表")
|
||||
bot.logger.info("开始加载群组列表与群成员列表")
|
||||
val troopData = FriendList.GetTroopListSimplify(
|
||||
bot.client
|
||||
).sendAndExpect<FriendList.GetTroopListSimplify.Response>(timeoutMillis = 1000)
|
||||
println("获取到群数量" + troopData.groups.size)
|
||||
val toGet: MutableMap<GroupImpl, ContactList<Member>> = mutableMapOf()
|
||||
troopData.groups.forEach {
|
||||
bot.groups.delegate.addLast(GroupImpl(bot, EmptyCoroutineContext, it.groupUin))
|
||||
val contactList = ContactList(LockFreeLinkedList<Member>())
|
||||
val group =
|
||||
GroupImpl(
|
||||
bot,
|
||||
EmptyCoroutineContext,
|
||||
it.groupUin,
|
||||
it.groupCode,
|
||||
it.groupName!!,
|
||||
it.groupMemo!!,
|
||||
contactList
|
||||
)
|
||||
group.owner =
|
||||
MemberImpl(QQImpl(bot, EmptyCoroutineContext, it.dwGroupOwnerUin!!), group, EmptyCoroutineContext)
|
||||
toGet[group] = contactList
|
||||
bot.groups.delegate.addLast(group)
|
||||
}
|
||||
bot.logger.info("群组列表加载完成, 共 ${troopData.groups.size}个")
|
||||
toGet.forEach {
|
||||
try {
|
||||
getTroopMemberList(it.key, it.value)
|
||||
} catch (e: Exception) {
|
||||
bot.logger.info("群${it.key.groupCode}的列表拉取失败, 将采用动态加入")
|
||||
}
|
||||
delay(200)
|
||||
}
|
||||
bot.logger.info("群组列表与群成员加载完成, 共 ${troopData.groups.size}个")
|
||||
} catch (e: Exception) {
|
||||
bot.logger.info("加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
suspend fun getTroopMemberList(groupUni: Long) {
|
||||
bot.logger.info("开始群[$groupUni]成员")
|
||||
val data = FriendList.GetTroopMemberList(
|
||||
bot.client,
|
||||
groupUni,
|
||||
0
|
||||
).sendAndExpect<FriendList.GetFriendGroupList.Response>(timeoutMillis = 1000)
|
||||
println(data.contentToString())
|
||||
suspend fun getTroopMemberList(group: GroupImpl, list: ContactList<Member>): ContactList<Member> {
|
||||
bot.logger.info("开始获取群[${group.groupCode}]成员列表")
|
||||
var size = 0
|
||||
var nextUin = 0L
|
||||
while (true) {
|
||||
val data = FriendList.GetTroopMemberList(
|
||||
bot.client,
|
||||
group.id,
|
||||
group.groupCode,
|
||||
nextUin
|
||||
).sendAndExpect<FriendList.GetTroopMemberList.Response>(timeoutMillis = 3000)
|
||||
data.members.forEach {
|
||||
list.delegate.addLast(
|
||||
MemberImpl(
|
||||
QQImpl(bot, EmptyCoroutineContext, it.memberUin),
|
||||
group,
|
||||
EmptyCoroutineContext
|
||||
)
|
||||
)
|
||||
}
|
||||
size += data.members.size
|
||||
nextUin = data.nextUin
|
||||
if (nextUin == 0L) {
|
||||
break
|
||||
}
|
||||
println("已获取群[${group.groupCode}]成员列表前" + size + "个成员")
|
||||
}
|
||||
println("群[${group.groupCode}]成员全部获取完成, 共${list.size}个成员")
|
||||
return list
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,7 +116,8 @@ internal object KnownPacketFactories {
|
||||
MessageSvc.PushForceOffline,
|
||||
MessageSvc.PbSendMsg,
|
||||
FriendList.GetFriendGroupList,
|
||||
FriendList.GetTroopListSimplify
|
||||
FriendList.GetTroopListSimplify,
|
||||
FriendList.GetTroopMemberList
|
||||
)
|
||||
|
||||
object IncomingFactories : List<IncomingPacketFactory<*>> by mutableListOf(
|
||||
|
@ -25,7 +25,7 @@ internal class OnlinePush {
|
||||
|
||||
val extraInfo: ImMsgBody.ExtraInfo? = pbPushMsg.msg.msgBody.richText.elems.firstOrNull { it.extraInfo != null }?.extraInfo
|
||||
|
||||
val group = bot.getGroup(pbPushMsg.msg.msgHead.groupInfo!!.groupCode)
|
||||
val group = bot.getGroupByGroupCode(pbPushMsg.msg.msgHead.groupInfo!!.groupCode)
|
||||
|
||||
val flags = extraInfo?.flags ?: 0
|
||||
return GroupMessage(
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.mamoe.mirai.qqandroid.network.protocol.packet.list
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.contact.GroupId
|
||||
import net.mamoe.mirai.contact.toInternalId
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket
|
||||
@ -27,16 +25,18 @@ internal class FriendList {
|
||||
|
||||
internal object GetTroopMemberList :
|
||||
OutgoingPacketFactory<GetTroopMemberList.Response>("friendlist.GetTroopMemberListReq") {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GetTroopMemberList.Response {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
||||
val res = this.debugIfFail { this.decodeUniPacket(GetTroopMemberListResp.serializer()) }
|
||||
return Response(
|
||||
res.vecTroopMember
|
||||
res.vecTroopMember,
|
||||
res.nextUin
|
||||
)
|
||||
}
|
||||
|
||||
operator fun invoke(
|
||||
client: QQAndroidClient,
|
||||
targetGroupId: Long,
|
||||
targetGroupCode: Long,
|
||||
nextUin: Long = 0
|
||||
): OutgoingPacket {
|
||||
return buildOutgoingUniPacket(client, bodyType = 1, key = client.wLoginSigInfo.d2Key) {
|
||||
@ -52,10 +52,11 @@ internal class FriendList {
|
||||
GetTroopMemberListReq.serializer(),
|
||||
GetTroopMemberListReq(
|
||||
uin = client.uin,
|
||||
groupCode = GroupId(targetGroupId).toInternalId().value,
|
||||
groupCode = targetGroupId,
|
||||
groupUin = targetGroupId,
|
||||
nextUin = nextUin,
|
||||
reqType = 0
|
||||
reqType = 0,
|
||||
version = 2
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -64,7 +65,8 @@ internal class FriendList {
|
||||
}
|
||||
|
||||
class Response(
|
||||
val members: List<stTroopMemberInfo>
|
||||
val members: List<stTroopMemberInfo>,
|
||||
val nextUin: Long
|
||||
) : Packet {
|
||||
override fun toString(): String = "Friendlist.GetTroopMemberList.Response"
|
||||
}
|
||||
@ -73,7 +75,6 @@ internal class FriendList {
|
||||
|
||||
internal object GetTroopListSimplify :
|
||||
OutgoingPacketFactory<GetTroopListSimplify.Response>("friendlist.GetTroopListReqV2") {
|
||||
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
||||
val res = this.decodeUniPacket(GetTroopListRespV2.serializer())
|
||||
return Response(res.vecTroopList.orEmpty())
|
||||
|
@ -67,19 +67,14 @@ abstract class Bot : CoroutineScope {
|
||||
* 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个.
|
||||
* 若 [id] 无效, 将会抛出 [GroupNotFoundException]
|
||||
*/
|
||||
abstract suspend fun getGroup(id: GroupId): Group
|
||||
abstract fun getGroupByID(id: Long): Group
|
||||
|
||||
/**
|
||||
* 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个.
|
||||
* 若 [internalId] 无效, 将会抛出 [GroupNotFoundException]
|
||||
*/
|
||||
abstract suspend fun getGroup(internalId: GroupInternalId): Group
|
||||
abstract fun getGroupByGroupCode(groupCode: Long): Group
|
||||
|
||||
/**
|
||||
* 获取缓存的群对象. 若没有对应的缓存, 则会线程安全地创建一个.
|
||||
* 若 [id] 无效, 将会抛出 [GroupNotFoundException]
|
||||
*/
|
||||
abstract suspend fun getGroup(id: Long): Group
|
||||
|
||||
// endregion
|
||||
|
||||
@ -132,11 +127,6 @@ abstract class Bot : CoroutineScope {
|
||||
fun Int.qq(): QQ = getQQ(this.toLong())
|
||||
fun Long.qq(): QQ = getQQ(this)
|
||||
|
||||
suspend inline fun Int.group(): Group = getGroup(this.toLong())
|
||||
suspend inline fun Long.group(): Group = getGroup(this)
|
||||
suspend inline fun GroupInternalId.group(): Group = getGroup(this)
|
||||
suspend inline fun GroupId.group(): Group = getGroup(this)
|
||||
|
||||
|
||||
/**
|
||||
* 需要调用者自行 close [output]
|
||||
|
@ -45,4 +45,10 @@ fun <C : Contact> LockFreeLinkedList<C>.getOrNull(id: Long): C? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun <C : Contact> LockFreeLinkedList<C>.getOrAdd(id: Long, supplier: () -> C): C = filteringGetOrAdd({ it.id == id }, supplier)
|
||||
inline fun <C : Contact> LockFreeLinkedList<C>.filterGetOrNull(filter: (C) -> Boolean): C? {
|
||||
forEach { if (filter(it)) return it }
|
||||
return null
|
||||
}
|
||||
|
||||
fun <C : Contact> LockFreeLinkedList<C>.getOrAdd(id: Long, supplier: () -> C): C =
|
||||
filteringGetOrAdd({ it.id == id }, supplier)
|
||||
|
@ -10,17 +10,16 @@ import net.mamoe.mirai.utils.coerceAtLeastOrFail
|
||||
/**
|
||||
* 群. 在 QQ Android 中叫做 "Troop"
|
||||
*
|
||||
* Group ID 与 Group Number 并不是同一个值.
|
||||
* - Group Number([Group.id]) 是通常使用的群号码.(在 QQ 客户端中可见)
|
||||
* - Group ID([Group.internalId]) 是与调用 API 时使用的 id.(在 QQ 客户端中不可见)
|
||||
* @author Him188moe
|
||||
* Group UIN 与 Group Code 并不是同一个值.
|
||||
* Group Code是在客户端显示的code
|
||||
* Group Uin是QQ内部的群ID[在Mirai中则为 id]
|
||||
* 但是有的时候 两个是相同的value
|
||||
* 在网络调用层 Code与Uin会被混用
|
||||
* 但在开发层 你应该只关注Group Code
|
||||
*/
|
||||
interface Group : Contact, CoroutineScope {
|
||||
/**
|
||||
* 内部 ID. 内部 ID 为 [GroupId] 的映射
|
||||
*/
|
||||
val internalId: GroupInternalId
|
||||
|
||||
val groupCode: Long
|
||||
/**
|
||||
* 群主 (同步事件更新)
|
||||
* 进行 [updateGroupInfo] 时将会更新这个值.
|
||||
@ -65,40 +64,4 @@ interface Group : Contact, CoroutineScope {
|
||||
suspend fun quit(): Boolean
|
||||
|
||||
fun toFullString(): String = "Group(id=${this.id}, name=$name, owner=${owner.id}, members=${members.idContentString})"
|
||||
}
|
||||
|
||||
/**
|
||||
* 一般的用户可见的 ID.
|
||||
* 在 TIM/QQ 客户端中所看到的的号码均是这个 ID.
|
||||
*
|
||||
* 注: 在引用群 ID 时, 只应使用 [GroupId] 或 [GroupInternalId] 类型 (内联类无性能损失), 而不能使用 [UInt].
|
||||
*
|
||||
* @see GroupInternalId.toId 由 [GroupInternalId] 转换为 [GroupId]
|
||||
* @see GroupId.toInternalId 由 [GroupId] 转换为 [GroupInternalId]
|
||||
*/
|
||||
inline class GroupId(inline val value: Long)
|
||||
|
||||
/**
|
||||
* 将 [this] 转为 [GroupInternalId].
|
||||
*/
|
||||
fun Long.groupInternalId(): GroupInternalId = GroupInternalId(this)
|
||||
|
||||
/**
|
||||
* 将无符号整数格式的 [Long] 转为 [GroupId].
|
||||
*
|
||||
* 注: 在 Java 中常用 [Long] 来表示 [UInt].
|
||||
*
|
||||
* 注: 在 Kotlin/Java, 有符号的数据类型的二进制最高位为符号标志.
|
||||
* 如一个 byte, `1000 0000` 最高位为 1, 则为负数.
|
||||
*/
|
||||
fun Long.groupId(): GroupId = GroupId(this.coerceAtLeastOrFail(0))
|
||||
|
||||
/**
|
||||
* 一些群 API 使用的 ID. 在使用时会特别注明
|
||||
*
|
||||
* 注: 在引用群 ID 时, 应使用 [GroupId] 或 [GroupInternalId] 类型, 而不是 [UInt]
|
||||
*
|
||||
* @see GroupInternalId.toId 由 [GroupInternalId] 转换为 [GroupId]
|
||||
* @see GroupId.toInternalId 由 [GroupId] 转换为 [GroupInternalId]
|
||||
*/
|
||||
inline class GroupInternalId(inline val value: Long)
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
||||
|
||||
package net.mamoe.mirai.contact
|
||||
|
||||
fun GroupId.toInternalId(): GroupInternalId {
|
||||
if (this.value <= 10.0e6) {
|
||||
return GroupInternalId(this.value)
|
||||
}
|
||||
val stringValue = this.value.toString()
|
||||
|
||||
fun plusLeft(leftIncrement: Int, rightLength: Int): String =
|
||||
stringValue.let { (it.dropLast(rightLength).toLong() + leftIncrement).toString() + it.takeLast(rightLength) }
|
||||
|
||||
return GroupInternalId(
|
||||
when (stringValue.dropLast(6).toInt()) {
|
||||
in 1..10 -> plusLeft(202, 6)
|
||||
in 11..19 -> plusLeft(469, 6)
|
||||
in 20..66 -> plusLeft(208, 7)
|
||||
in 67..156 -> plusLeft(1943, 6)
|
||||
in 157..209 -> plusLeft(199, 7)
|
||||
in 210..309 -> plusLeft(389, 7)
|
||||
in 310..499 -> plusLeft(349, 7)
|
||||
else -> null
|
||||
}?.toLong() ?: this.value
|
||||
)
|
||||
}
|
||||
|
||||
fun GroupInternalId.toId(): GroupId = with(value.toString()) {
|
||||
if (value < 10.0e6) {
|
||||
return GroupId(value)
|
||||
}
|
||||
val left = this.dropLast(6).toLong()
|
||||
|
||||
return GroupId(
|
||||
when (left.toInt()) {
|
||||
in 203..212 -> ((left - 202).toString() + this.takeLast(6).toInt().toString()).toLong()
|
||||
in 480..488 -> ((left - 469).toString() + this.takeLast(6).toInt().toString()).toLong()
|
||||
in 2100..2146 -> ((left.toString().take(3).toLong() - 208).toString() + this.takeLast(7).toInt().toString()).toLong()
|
||||
in 2010..2099 -> ((left - 1943).toString() + this.takeLast(6).toInt().toString()).toLong()
|
||||
in 2147..2199 -> ((left.toString().take(3).toLong() - 199).toString() + this.takeLast(7).toInt().toString()).toLong()
|
||||
in 4100..4199 -> ((left.toString().take(3).toLong() - 389).toString() + this.takeLast(7).toInt().toString()).toLong()
|
||||
in 3800..3989 -> ((left.toString().take(3).toLong() - 349).toString() + this.takeLast(7).toInt().toString()).toLong()
|
||||
else -> value
|
||||
}
|
||||
)
|
||||
}
|
@ -79,8 +79,4 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) :
|
||||
fun Int.qq(): QQ = bot.getQQ(this.coerceAtLeastOrFail(0).toLong())
|
||||
fun Long.qq(): QQ = bot.getQQ(this.coerceAtLeastOrFail(0))
|
||||
|
||||
suspend inline fun Int.group(): Group = bot.getGroup(this.coerceAtLeastOrFail(0).toLong())
|
||||
suspend inline fun Long.group(): Group = bot.getGroup(this.coerceAtLeastOrFail(0))
|
||||
suspend inline fun GroupId.group(): Group = bot.getGroup(this)
|
||||
suspend inline fun GroupInternalId.group(): Group = bot.getGroup(this)
|
||||
}
|
@ -7,10 +7,6 @@ import kotlinx.io.charsets.Charset
|
||||
import kotlinx.io.charsets.Charsets
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.io.pool.useInstance
|
||||
import net.mamoe.mirai.contact.GroupId
|
||||
import net.mamoe.mirai.contact.GroupInternalId
|
||||
import net.mamoe.mirai.contact.groupId
|
||||
import net.mamoe.mirai.contact.groupInternalId
|
||||
import net.mamoe.mirai.utils.assertUnreachable
|
||||
import net.mamoe.mirai.utils.cryptor.contentToString
|
||||
import kotlin.jvm.JvmName
|
||||
@ -70,8 +66,8 @@ fun Input.readIP(): String = buildString(4 + 3) {
|
||||
|
||||
fun Input.readQQ(): Long = this.readUInt().toLong()
|
||||
fun Input.readGroup(): Long = this.readUInt().toLong()
|
||||
fun Input.readGroupId(): GroupId = this.readUInt().toLong().groupId()
|
||||
fun Input.readGroupInternalId(): GroupInternalId = this.readUInt().toLong().groupInternalId()
|
||||
fun Input.readGroupId(): Long = this.readUInt().toLong()
|
||||
fun Input.readGroupCode(): Long = this.readUInt().toLong()
|
||||
|
||||
fun Input.readUVarIntLVString(): String = String(this.readUVarIntByteArray())
|
||||
|
||||
|
@ -4,8 +4,6 @@ package net.mamoe.mirai.utils.io
|
||||
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.io.pool.useInstance
|
||||
import net.mamoe.mirai.contact.GroupId
|
||||
import net.mamoe.mirai.contact.GroupInternalId
|
||||
import net.mamoe.mirai.utils.Tested
|
||||
import net.mamoe.mirai.utils.coerceAtMostOrFail
|
||||
import net.mamoe.mirai.utils.cryptor.encryptBy
|
||||
@ -23,8 +21,7 @@ fun BytePacketBuilder.writeZero(count: Int) {
|
||||
fun BytePacketBuilder.writeRandom(length: Int) = repeat(length) { this.writeByte(Random.Default.nextInt(255).toByte()) }
|
||||
|
||||
fun BytePacketBuilder.writeQQ(qq: Long) = this.writeUInt(qq.toUInt()) // same bit rep.
|
||||
fun BytePacketBuilder.writeGroup(groupId: GroupId) = this.writeUInt(groupId.value.toUInt())
|
||||
fun BytePacketBuilder.writeGroup(groupInternalId: GroupInternalId) = this.writeUInt(groupInternalId.value.toUInt())
|
||||
fun BytePacketBuilder.writeGroup(groupId: Long) = this.writeUInt(groupId.toUInt())
|
||||
|
||||
fun BytePacketBuilder.writeShortLVByteArrayLimitedLength(array: ByteArray, maxLength: Int) {
|
||||
if (array.size <= maxLength) {
|
||||
|
Loading…
Reference in New Issue
Block a user