Merge remote-tracking branch 'origin/master'

This commit is contained in:
ryoii 2020-03-08 22:48:00 +08:00
commit 712256488d
161 changed files with 7664 additions and 5633 deletions

19
.github/ISSUE_TEMPLATE/----.md vendored Normal file
View File

@ -0,0 +1,19 @@
---
name: 特性申请
about: 申请 mirai 添加新的特性
title: ''
labels: feature
assignees: ''
---
以下相关功能将会被直接拒绝:
- 资金相关: 红包, 转账
- 主动加好友, 主动加群, 主动邀请加入群
可以提交的内容:
- 有较高使用频率的协议 (低频功能不接受提议)
- 架构 / 功能上的建议 (欢迎)
请删除以上内容后再描述问题

17
.github/ISSUE_TEMPLATE/bug---.md vendored Normal file
View File

@ -0,0 +1,17 @@
---
name: Bug 报告
about: 提交一个 bug
title: ''
labels: " bug "
assignees: ''
---
提交前请先确认:
- 已经在现有 issue 列表中检查并未发现重复问题
- 确认问题属于 `mirai-core`, 而不是 `mirai-console` 或其他
若有报错, 请尽可能附加完整控制台日志或截图
若无报错, 请尽可能描述如何复现这个问题
请删除以上内容后再描述问题

40
.github/workflows/main2.yml vendored Normal file
View File

@ -0,0 +1,40 @@
# This is a basic workflow to help you get started with Actions
name: Shadow
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
release:
types:
- created
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle and shadowJar
run: ./gradlew :mirai-core:shadowJar :mirai-core-qqandroid:shadowJar
- name: Upload artifact
uses: actions/upload-artifact@v1.0.0
with:
# Artifact name
name: mirai-core-all
# Directory containing files to upload
path: "mirai-core/build/libs/mirai-core-*-all.jar"
- name: Upload artifact
uses: actions/upload-artifact@v1.0.0
with:
# Artifact name
name: mirai-core-qqandroid-all
# Directory containing files to upload
path: "mirai-core-qqandroid/build/libs/mirai-core-qqandroid-*-all.jar"

View File

@ -2,12 +2,29 @@
开发版本. 频繁更新, 不保证高稳定性
## `0.25.0` 还未发布
## `0.27.0` 2020/3/8
- 支持 `XML`, `Json`, `LightApp``RichMessage`
## `0.26.2` 2020/3/8
- 新增 `MessageChain.repeat``MessageChain.times`
- JVM 平台下 `PlatformLogger` 可重定向输出
- 修复 `NullMessageChain.equals` 判断不正确的问题
- 新增 `PlainText.of` 以应对一些特殊情况
## `0.26.1` 2020/3/8
- 重写 Jce 序列化, 提升反序列性能
- 更新 `Kotlin` 版本到 1.3.70
- 更新 `kotlinx.coroutines`, `atomicfu`, `kotlinx.coroutines` 依赖版本
## `0.26.0` 2020/3/7
- 使用 `kotlinx.io` 而不是 `ktor.io`
- 修复 #111, #108, #116, #112
## `0.25.0` 2020/3/6
- 适配 8.2.7 版本2020 年 3 月)协议
- 全面的 `Image` 类型: Online/Offline Image, Friend/Group Image
- 修复查询图片链接时好友图片链接错误的问题
- Kotlin 1.3.70
- 修复事件处理错误 (#107)
- 修复 bugs: #105, #106, #107
## `0.24.1` 2020/3/3
- 修复 `Member` 的委托 `QQ` 弱引用被释放的问题

View File

@ -61,7 +61,7 @@ Demos: [mirai-demos](https://github.com/mamoe/mirai-demos)
### 使用者
- [mirai-console](https://github.com/mamoe/mirai/tree/master/mirai-console) 支持插件 **本模块正在完善**
- [mirai-console](https://github.com/mamoe/mirai-console) 支持插件 **本模块正在完善**
### 我是其他平台的使用者

View File

@ -4,12 +4,11 @@ import java.util.*
buildscript {
repositories {
mavenLocal()
maven { setUrl("https://mirrors.huaweicloud.com/repository/maven") }
maven(url = "https://mirrors.huaweicloud.com/repository/maven")
jcenter()
mavenCentral()
// mavenCentral()
google()
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-dev") }
// maven (url="https://dl.bintray.com/kotlin/kotlin-eap")
}
dependencies {
@ -41,11 +40,10 @@ allprojects {
repositories {
mavenLocal()
maven { setUrl("https://mirrors.huaweicloud.com/repository/maven") }
maven(url = "https://mirrors.huaweicloud.com/repository/maven")
jcenter()
mavenCentral()
// mavenCentral()
google()
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-dev") }
// maven (url="https://dl.bintray.com/kotlin/kotlin-eap")
}
}

View File

@ -1,15 +1,16 @@
# style guide
kotlin.code.style=official
# config
miraiVersion=0.24.1
miraiVersion=0.27.0
kotlin.incremental.multiplatform=true
kotlin.parallel.tasks.in.project=true
# kotlin
kotlinVersion=1.3.61
kotlinVersion=1.3.70
# kotlin libraries
serializationVersion=0.14.0
coroutinesVersion=1.3.3
serializationVersion=0.20.0
coroutinesVersion=1.3.4
atomicFuVersion=0.14.1
kotlinXIoVersion=0.1.16
coroutinesIoVersion=0.1.16
# utility
ktorVersion=1.3.1

View File

@ -8,9 +8,12 @@ plugins {
id("com.jfrog.bintray") version "1.8.4-jetbrains-3"
}
apply(plugin = "com.github.johnrengelman.shadow")
val kotlinVersion: String by rootProject.ext
val atomicFuVersion: String by rootProject.ext
val coroutinesVersion: String by rootProject.ext
val kotlinXIoVersion: String by rootProject.ext
val coroutinesIoVersion: String by rootProject.ext
@ -66,6 +69,7 @@ kotlin {
api(kotlin("stdlib", kotlinVersion))
api("org.jetbrains.kotlinx:atomicfu:$atomicFuVersion")
api(kotlinx("io", kotlinXIoVersion))
api(kotlinx("coroutines-io", coroutinesIoVersion))
api(kotlinx("coroutines-core", coroutinesVersion))
}
@ -73,6 +77,7 @@ kotlin {
commonMain {
dependencies {
api(kotlinx("serialization-runtime-common", serializationVersion))
api(kotlinx("serialization-protobuf-common", serializationVersion))
}
}
commonTest {
@ -86,6 +91,7 @@ kotlin {
if (isAndroidSDKAvailable) {
val androidMain by getting {
dependencies {
api(kotlinx("serialization-protobuf", serializationVersion))
}
}

View File

@ -21,7 +21,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
*/
@Suppress("INAPPLICABLE_JVM_NAME")
actual object QQAndroid : BotFactory {
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
@JvmName("newBot")
actual override fun Bot(context: Context, qq: Long, password: String, configuration: BotConfiguration): Bot {
return QQAndroidBot(context, BotAccount(qq, password), configuration)
@ -30,7 +30,7 @@ actual object QQAndroid : BotFactory {
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
@JvmName("newBot")
actual override fun Bot(
context: Context,

View File

@ -9,15 +9,188 @@
package net.mamoe.mirai.qqandroid
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.consumeEachBufferRange
import io.ktor.utils.io.core.Input
import io.ktor.utils.io.core.readBytes
import kotlinx.coroutines.io.*
import kotlinx.io.core.*
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.io.ByteArrayPool
import net.mamoe.mirai.utils.io.toReadPacket
import java.nio.ByteBuffer
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal actual class QQAndroidBot
actual constructor(
context: Context,
account: BotAccount,
configuration: BotConfiguration
) : QQAndroidBotBase(context, account, configuration)
) : QQAndroidBotBase(context, account, configuration)
@OptIn(MiraiInternalAPI::class)
@Suppress("DEPRECATION")
internal actual fun ByteReadChannel.toKotlinByteReadChannel(): kotlinx.coroutines.io.ByteReadChannel {
return object : kotlinx.coroutines.io.ByteReadChannel {
override val availableForRead: Int
get() = this@toKotlinByteReadChannel.availableForRead
override val isClosedForRead: Boolean
get() = this@toKotlinByteReadChannel.isClosedForRead
override val isClosedForWrite: Boolean
get() = this@toKotlinByteReadChannel.isClosedForWrite
@Suppress("DEPRECATION_ERROR", "OverridingDeprecatedMember")
override var readByteOrder: ByteOrder
get() = when (this@toKotlinByteReadChannel.readByteOrder) {
io.ktor.utils.io.core.ByteOrder.BIG_ENDIAN -> ByteOrder.BIG_ENDIAN
io.ktor.utils.io.core.ByteOrder.LITTLE_ENDIAN -> ByteOrder.LITTLE_ENDIAN
}
set(value) {
this@toKotlinByteReadChannel.readByteOrder = when (value) {
ByteOrder.BIG_ENDIAN -> io.ktor.utils.io.core.ByteOrder.BIG_ENDIAN
ByteOrder.LITTLE_ENDIAN -> io.ktor.utils.io.core.ByteOrder.LITTLE_ENDIAN
}
}
@Suppress("DEPRECATION_ERROR", "DEPRECATION", "OverridingDeprecatedMember")
override val totalBytesRead: Long
get() = this@toKotlinByteReadChannel.totalBytesRead
override fun cancel(cause: Throwable?): Boolean = this@toKotlinByteReadChannel.cancel(cause)
override suspend fun consumeEachBufferRange(visitor: ConsumeEachBufferVisitor) =
this@toKotlinByteReadChannel.consumeEachBufferRange(visitor)
override suspend fun discard(max: Long): Long = this@toKotlinByteReadChannel.discard(max)
@Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE")
@ExperimentalIoApi
override fun <R> lookAhead(visitor: LookAheadSession.() -> R): R {
return this@toKotlinByteReadChannel.lookAhead l@{
visitor(object : LookAheadSession {
override fun consumed(n: Int) {
return this@l.consumed(n)
}
override fun request(skip: Int, atLeast: Int): ByteBuffer? {
return this@l.request(skip, atLeast)
}
})
}
}
@Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE")
@ExperimentalIoApi
override suspend fun <R> lookAheadSuspend(visitor: suspend LookAheadSuspendSession.() -> R): R =
this@toKotlinByteReadChannel.lookAheadSuspend l@{
visitor(object : LookAheadSuspendSession {
override suspend fun awaitAtLeast(n: Int): Boolean {
return this@l.awaitAtLeast(n)
}
override fun consumed(n: Int) {
return this@l.consumed(n)
}
override fun request(skip: Int, atLeast: Int): ByteBuffer? {
return this@l.request(skip, atLeast)
}
})
}
override suspend fun read(min: Int, consumer: (ByteBuffer) -> Unit) =
this@toKotlinByteReadChannel.read(min, consumer)
override suspend fun readAvailable(dst: ByteBuffer): Int = this@toKotlinByteReadChannel.readAvailable(dst)
override suspend fun readAvailable(dst: ByteArray, offset: Int, length: Int): Int =
this@toKotlinByteReadChannel.readAvailable(dst, offset, length)
override suspend fun readAvailable(dst: IoBuffer): Int {
ByteArrayPool.useInstance {
val read = this@toKotlinByteReadChannel.readAvailable(it, 0, it.size)
dst.writeFully(it, 0, read)
return read
}
}
override suspend fun readBoolean(): Boolean = this@toKotlinByteReadChannel.readBoolean()
override suspend fun readByte(): Byte = this@toKotlinByteReadChannel.readByte()
override suspend fun readDouble(): Double = this@toKotlinByteReadChannel.readDouble()
override suspend fun readFloat(): Float = this@toKotlinByteReadChannel.readFloat()
override suspend fun readFully(dst: ByteBuffer): Int {
TODO("not implemented")
}
override suspend fun readFully(dst: ByteArray, offset: Int, length: Int) =
this@toKotlinByteReadChannel.readFully(dst, offset, length)
override suspend fun readFully(dst: IoBuffer, n: Int) {
ByteArrayPool.useInstance {
dst.writeFully(it, 0, this.readAvailable(it, 0, it.size))
}
}
override suspend fun readInt(): Int = this@toKotlinByteReadChannel.readInt()
override suspend fun readLong(): Long = this@toKotlinByteReadChannel.readLong()
override suspend fun readPacket(size: Int, headerSizeHint: Int): ByteReadPacket {
return this@toKotlinByteReadChannel.readPacket(size, headerSizeHint).readBytes().toReadPacket()
}
override suspend fun readRemaining(limit: Long, headerSizeHint: Int): ByteReadPacket {
return this@toKotlinByteReadChannel.readRemaining(limit, headerSizeHint).readBytes().toReadPacket()
}
@OptIn(ExperimentalIoApi::class)
@ExperimentalIoApi
override fun readSession(consumer: ReadSession.() -> Unit) {
@Suppress("DEPRECATION")
this@toKotlinByteReadChannel.readSession lambda@{
consumer(object : ReadSession {
override val availableForRead: Int
get() = this@lambda.availableForRead
override fun discard(n: Int): Int = this@lambda.discard(n)
override fun request(atLeast: Int): IoBuffer? {
val ioBuffer: io.ktor.utils.io.core.IoBuffer = this@lambda.request(atLeast) ?: return null
val buffer = IoBuffer.Pool.borrow()
val bytes = (ioBuffer as Input).readBytes()
buffer.writeFully(bytes)
return buffer
}
})
}
}
override suspend fun readShort(): Short = this@toKotlinByteReadChannel.readShort()
@Suppress("EXPERIMENTAL_OVERRIDE", "EXPERIMENTAL_API_USAGE")
@ExperimentalIoApi
override suspend fun readSuspendableSession(consumer: suspend SuspendableReadSession.() -> Unit) =
this@toKotlinByteReadChannel.readSuspendableSession l@{
consumer(object : SuspendableReadSession {
override val availableForRead: Int
get() = this@l.availableForRead
override suspend fun await(atLeast: Int): Boolean = this@l.await(atLeast)
override fun discard(n: Int): Int = this@l.discard(n)
override fun request(atLeast: Int): IoBuffer? {
@Suppress("DuplicatedCode") val ioBuffer: io.ktor.utils.io.core.IoBuffer =
this@l.request(atLeast) ?: return null
val buffer = IoBuffer.Pool.borrow()
val bytes = (ioBuffer as Input).readBytes()
buffer.writeFully(bytes)
return buffer
}
})
}
override suspend fun readUTF8Line(limit: Int): String? = this@toKotlinByteReadChannel.readUTF8Line(limit)
override suspend fun <A : Appendable> readUTF8LineTo(out: A, limit: Int): Boolean =
this@toKotlinByteReadChannel.readUTF8LineTo(out, limit)
}
}

View File

@ -9,9 +9,9 @@
package net.mamoe.mirai.qqandroid
import io.ktor.utils.io.core.Closeable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.io.core.Closeable
import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.*
@ -78,6 +78,7 @@ internal class QQImpl(
return MessageReceipt(source, this, null)
}
@OptIn(MiraiInternalAPI::class)
override suspend fun uploadImage(image: ExternalImage): OfflineFriendImage = try {
if (BeforeImageUploadEvent(this, image).broadcast().isCancelled) {
throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup")
@ -111,7 +112,7 @@ internal class QQImpl(
ImageUploadEvent.Succeed(this@QQImpl, image, it).broadcast()
}
is LongConn.OffPicUp.Response.RequireUpload -> {
Http.postImage(
MiraiPlatformUtils.Http.postImage(
"0x6ff0070",
bot.uin,
null,
@ -358,7 +359,7 @@ internal class MemberInfoImpl(
override val muteTimestamp: Int = jceInfo.dwShutupTimestap?.toInt() ?: 0
}
@UseExperimental(ExperimentalContracts::class)
@OptIn(ExperimentalContracts::class)
internal fun GroupImpl.Companion.checkIsInstance(expression: Boolean) {
contract {
returns() implies expression
@ -367,13 +368,14 @@ internal fun GroupImpl.Companion.checkIsInstance(expression: Boolean) {
}
@Suppress("PropertyName")
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal class GroupImpl(
bot: QQAndroidBot, override val coroutineContext: CoroutineContext,
override val id: Long,
groupInfo: GroupInfo,
members: Sequence<MemberInfo>
) : Group() {
@Suppress("\"RemoveEmptyClassBody\"") // things will go wrong after removal, don't try
companion object {
}
@ -383,7 +385,7 @@ internal class GroupImpl(
override lateinit var owner: Member
@UseExperimental(MiraiExperimentalAPI::class)
@OptIn(MiraiExperimentalAPI::class)
override val botAsMember: Member by lazy {
Member(object : MemberInfo {
override val nameCard: String
@ -401,7 +403,7 @@ internal class GroupImpl(
})
}
@UseExperimental(MiraiExperimentalAPI::class)
@OptIn(MiraiExperimentalAPI::class)
override lateinit var botPermission: MemberPermission
var _botMuteTimestamp: Int = groupInfo.botMuteRemaining
@ -557,10 +559,10 @@ internal class GroupImpl(
TODO("not implemented")
}
@UseExperimental(MiraiExperimentalAPI::class)
@OptIn(MiraiExperimentalAPI::class)
override fun Member(memberInfo: MemberInfo): Member {
return MemberImpl(
@UseExperimental(LowLevelAPI::class)
@OptIn(LowLevelAPI::class)
bot._lowLevelNewQQ(memberInfo) as QQImpl,
this,
this.coroutineContext,

View File

@ -11,8 +11,8 @@ package net.mamoe.mirai.qqandroid
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import io.ktor.utils.io.ByteReadChannel
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.io.ByteReadChannel
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.BotImpl
import net.mamoe.mirai.LowLevelAPI
@ -36,14 +36,14 @@ import net.mamoe.mirai.utils.*
import kotlin.collections.asSequence
import kotlin.coroutines.CoroutineContext
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal expect class QQAndroidBot constructor(
context: Context,
account: BotAccount,
configuration: BotConfiguration
) : QQAndroidBotBase
@UseExperimental(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
internal abstract class QQAndroidBotBase constructor(
context: Context,
account: BotAccount,
@ -69,7 +69,7 @@ internal abstract class QQAndroidBotBase constructor(
override val friends: ContactList<QQ> = ContactList(LockFreeLinkedList())
override val selfQQ: QQ by lazy {
@UseExperimental(LowLevelAPI::class)
@OptIn(LowLevelAPI::class)
_lowLevelNewQQ(object : FriendInfo {
override val uin: Long get() = this@QQAndroidBotBase.uin
override val nick: String get() = this@QQAndroidBotBase.nick
@ -101,7 +101,7 @@ internal abstract class QQAndroidBotBase constructor(
return groups.delegate.getOrNull(uin)
}
@UseExperimental(LowLevelAPI::class)
@OptIn(LowLevelAPI::class)
override suspend fun _lowLevelQueryGroupList(): Sequence<Long> {
return network.run {
FriendList.GetTroopListSimplify(bot.client)
@ -109,7 +109,7 @@ internal abstract class QQAndroidBotBase constructor(
}.groups.asSequence().map { it.groupUin.shl(32) and it.groupCode }
}
@UseExperimental(LowLevelAPI::class)
@OptIn(LowLevelAPI::class)
override suspend fun _lowLevelQueryGroupInfo(groupCode: Long): GroupInfo = network.run {
TroopManagement.GetGroupInfo(
client = bot.client,
@ -117,7 +117,7 @@ internal abstract class QQAndroidBotBase constructor(
).sendAndExpect<GroupInfoImpl>(retry = 2)
}
@UseExperimental(LowLevelAPI::class)
@OptIn(LowLevelAPI::class)
override suspend fun _lowLevelQueryGroupMemberList(
groupUin: Long,
groupCode: Long,
@ -187,7 +187,7 @@ internal abstract class QQAndroidBotBase constructor(
}
}
@UseExperimental(LowLevelAPI::class)
@OptIn(LowLevelAPI::class)
override suspend fun _lowLevelRecallFriendMessage(friendId: Long, messageId: Long, time: Long) {
network.run {
val response: PbMessageSvc.PbMsgWithDraw.Response =
@ -198,7 +198,7 @@ internal abstract class QQAndroidBotBase constructor(
}
}
@UseExperimental(LowLevelAPI::class)
@OptIn(LowLevelAPI::class)
override suspend fun _lowLevelRecallGroupMessage(groupId: Long, messageId: Long) {
network.run {
val response: PbMessageSvc.PbMsgWithDraw.Response =
@ -222,6 +222,10 @@ internal abstract class QQAndroidBotBase constructor(
}
override suspend fun openChannel(image: Image): ByteReadChannel {
return Http.get<HttpResponse>(queryImageUrl(image)).content
return MiraiPlatformUtils.Http.get<HttpResponse>(queryImageUrl(image)).content.toKotlinByteReadChannel()
}
}
}
@Suppress("DEPRECATION")
@OptIn(MiraiInternalAPI::class)
internal expect fun io.ktor.utils.io.ByteReadChannel.toKotlinByteReadChannel(): ByteReadChannel

View File

@ -0,0 +1,14 @@
package net.mamoe.mirai.qqandroid.io.serialization
import kotlinx.io.core.Input
import kotlinx.io.core.Output
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialFormat
import kotlinx.serialization.SerializationStrategy
interface IOFormat : SerialFormat {
fun <T> dumpTo(serializer: SerializationStrategy<T>, ojb: T, output: Output)
fun <T> load(deserializer: DeserializationStrategy<T>, input: Input): T
}

View File

@ -9,19 +9,42 @@
package net.mamoe.mirai.qqandroid.io.serialization
import io.ktor.utils.io.charsets.Charset
import io.ktor.utils.io.core.*
import kotlinx.io.charsets.Charset
import kotlinx.io.core.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.ByteArraySerializer
import kotlinx.serialization.builtins.MapEntrySerializer
import kotlinx.serialization.builtins.SetSerializer
import kotlinx.serialization.internal.*
import kotlinx.serialization.modules.EmptyModule
import kotlinx.serialization.modules.SerialModule
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.BYTE
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.DOUBLE
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.FLOAT
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.INT
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.JCE_MAX_STRING_LENGTH
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.LIST
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.LONG
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.MAP
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.SHORT
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.SIMPLE_LIST
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.STRING1
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.STRING4
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.STRUCT_BEGIN
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.STRUCT_END
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.ZERO_TYPE
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceHead
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.utils.io.readString
import net.mamoe.mirai.utils.io.toReadPacket
@PublishedApi
internal val CharsetGBK = Charset.forName("GBK")
@PublishedApi
internal val CharsetUTF8 = Charset.forName("UTF8")
@ -30,12 +53,15 @@ enum class JceCharset(val kotlinCharset: Charset) {
UTF8(Charset.forName("UTF8"))
}
internal fun getSerialId(desc: SerialDescriptor, index: Int): Int? = desc.findAnnotation<SerialId>(index)?.id
internal fun getSerialId(desc: SerialDescriptor, index: Int): Int? = desc.findAnnotation<JceId>(index)?.id
/**
* Jce 数据结构序列化和反序列化工具, 能将 kotlinx.serialization 通用的注解标记格式的 `class` 序列化为 [ByteArray]
*/
class Jce private constructor(private val charset: JceCharset, context: SerialModule = EmptyModule) : AbstractSerialFormat(context), BinaryFormat {
@Suppress("DEPRECATION_ERROR")
@OptIn(InternalSerializationApi::class)
class JceOld private constructor(private val charset: JceCharset, override val context: SerialModule = EmptyModule) :
SerialFormat, BinaryFormat {
private inner class ListWriter(
private val count: Int,
@ -46,7 +72,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
return 0
}
override fun endEncode(desc: SerialDescriptor) {
override fun endEncode(descriptor: SerialDescriptor) {
parentEncoder.writeHead(LIST, this.tag)
parentEncoder.encodeTaggedInt(0, count)
parentEncoder.output.writePacket(this.output.build())
@ -68,11 +94,18 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
parentEncoder.output.write(this.output.toByteArray())
}*/
override fun beginCollection(desc: SerialDescriptor, collectionSize: Int, vararg typeParams: KSerializer<*>): CompositeEncoder {
override fun beginCollection(
descriptor: SerialDescriptor,
collectionSize: Int,
vararg typeSerializers: KSerializer<*>
): CompositeEncoder {
return this
}
override fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeEncoder {
override fun beginStructure(
descriptor: SerialDescriptor,
vararg typeSerializers: KSerializer<*>
): CompositeEncoder {
return this
}
}
@ -81,11 +114,11 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
* From: com.qq.taf.jce.JceOutputStream
*/
@Suppress("unused", "MemberVisibilityCanBePrivate")
@UseExperimental(ExperimentalIoApi::class)
@OptIn(ExperimentalIoApi::class)
private open inner class JceEncoder(
internal val output: BytePacketBuilder
) : TaggedEncoder<Int>() {
override val context get() = this@Jce.context
override val context get() = this@JceOld.context
override fun SerialDescriptor.getTag(index: Int): Int {
return getSerialId(this, index) ?: error("cannot find @SerialId")
@ -94,28 +127,38 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
/**
* 序列化最开始的时候的
*/
override fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeEncoder = when (desc.kind) {
StructureKind.LIST -> this
StructureKind.MAP -> this
StructureKind.CLASS, UnionKind.OBJECT -> this
is PolymorphicKind -> this
else -> throw SerializationException("Primitives are not supported at top-level")
}
@UseExperimental(ImplicitReflectionSerializer::class)
@Suppress("UNCHECKED_CAST", "NAME_SHADOWING")
override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) = when (serializer.descriptor) {
is MapLikeDescriptor -> {
val entries = (value as Map<*, *>).entries
val serializer = (serializer as MapLikeSerializer<Any?, Any?, T, *>)
val mapEntrySerial = MapEntrySerializer(serializer.keySerializer, serializer.valueSerializer)
this.writeHead(MAP, currentTag)
this.encodeTaggedInt(0, entries.count())
HashSetSerializer(mapEntrySerial).serialize(JceMapWriter(this.output), entries)
override fun beginStructure(
descriptor: SerialDescriptor,
vararg typeSerializers: KSerializer<*>
): CompositeEncoder =
when (descriptor.kind) {
StructureKind.LIST -> this
StructureKind.MAP -> this
StructureKind.CLASS, StructureKind.OBJECT -> this
is PolymorphicKind -> this
else -> throw SerializationException("Primitives are not supported at top-level")
}
ByteArraySerializer.descriptor -> encodeTaggedByteArray(popTag(), value as ByteArray)
is PrimitiveArrayDescriptor -> {
@OptIn(ImplicitReflectionSerializer::class)
@Suppress("UNCHECKED_CAST", "NAME_SHADOWING")
override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) = when {
serializer.descriptor.kind == StructureKind.MAP -> {
try {
val entries = (value as Map<*, *>).entries
val serializer = (serializer as MapLikeSerializer<Any?, Any?, T, *>)
val mapEntrySerial = MapEntrySerializer(serializer.keySerializer, serializer.valueSerializer)
this.writeHead(MAP, currentTag)
this.encodeTaggedInt(0, entries.count())
SetSerializer(mapEntrySerial).serialize(JceMapWriter(this.output), entries)
} catch (e: Exception) {
super.encodeSerializableValue(serializer, value)
}
}
serializer.descriptor.kind == StructureKind.LIST
&& value is ByteArray -> encodeTaggedByteArray(popTag(), value as ByteArray)
serializer.descriptor.kind == StructureKind.LIST
&& serializer.descriptor.getElementDescriptor(0) is PrimitiveKind -> {
serializer.serialize(
ListWriter(
when (value) {
@ -133,9 +176,8 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
value
)
}
is ArrayClassDesc -> {
val descriptor = serializer.descriptor as ReferenceArraySerializer<Any, Any?>
if (descriptor.typeParams.isNotEmpty() && descriptor.typeParams[0] is ByteSerializer) {
serializer.descriptor.kind == StructureKind.LIST && value is Array<*> -> {
if (serializer.descriptor.getElementDescriptor(0).kind is PrimitiveKind.BYTE) {
encodeTaggedByteArray(popTag(), (value as Array<Byte>).toByteArray())
} else
serializer.serialize(
@ -143,7 +185,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
value
)
}
is ListLikeDescriptor -> {
serializer.descriptor.kind == StructureKind.LIST -> {
serializer.serialize(
ListWriter((value as Collection<*>).size, popTag(), this),
value
@ -262,7 +304,8 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
is Double -> encodeTaggedDouble(tag, value)
is Boolean -> encodeTaggedBoolean(tag, value)
is String -> encodeTaggedString(tag, value)
is Unit -> encodeTaggedUnit(tag)
is Unit -> {
}
else -> error("unsupported type: ${value.getClassName()}")
}
}
@ -286,7 +329,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
val size: Int,
input: JceInput
) : JceDecoder(input) {
override fun decodeCollectionSize(desc: SerialDescriptor): Int {
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
return size
}
@ -300,7 +343,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
val size: Int,
input: JceInput
) : JceDecoder(input) {
override fun decodeCollectionSize(desc: SerialDescriptor): Int {
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
return size
}
@ -312,7 +355,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
private open inner class JceStructReader(
input: JceInput
) : JceDecoder(input) {
override fun endStructure(desc: SerialDescriptor) {
override fun endStructure(descriptor: SerialDescriptor) {
}
}
@ -342,22 +385,27 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
return input.readInt(tag)
}
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
return 0
}
/**
* [KSerializer.serialize]
*/
override fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
//// println("beginStructure: desc=${desc.getClassName()}, typeParams: ${typeParams.contentToString()}")
when (desc) {
when {
// 由于 Byte 的数组有两种方式写入, 需特定读取器
ByteArraySerializer.descriptor -> {
descriptor.kind == StructureKind.LIST
&& descriptor.getElementDescriptor(0).kind == PrimitiveKind.BYTE -> {
// ByteArray, 交给 decodeSerializableValue 进行处理
return this
}
is ListLikeDescriptor -> {
if (typeParams.isNotEmpty() && typeParams[0] is ByteSerializer) {
// Array<Byte>
return this // 交给 decodeSerializableValue
}
descriptor.kind == StructureKind.LIST -> {
// if (typeParams.isNotEmpty() && typeParams[0] is ByteSerializer) {
// // Array<Byte>
// return this // 交给 decodeSerializableValue
// }
val tag = currentTagOrNull
@Suppress("SENSELESS_COMPARISON") // 推断 bug
@ -371,12 +419,12 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
MAP -> JceMapReader(input.readInt(0), this.input)
else -> error("type mismatch")
}
} == null && desc.isNullable) {
} == null && descriptor.isNullable) {
return NullReader(this.input)
}
}
is MapLikeDescriptor -> {
descriptor.kind == StructureKind.MAP -> {
val tag = currentTagOrNull
if (tag != null) {
popTag()
@ -391,7 +439,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
return NullReader(this.input)
}
return super.beginStructure(desc, *typeParams)
return super.beginStructure(descriptor, *typeParams)
}
override fun decodeTaggedNull(tag: Int): Nothing? {
@ -410,7 +458,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
@Suppress("UNCHECKED_CAST")
override fun <T : Any> decodeNullableSerializableValue(deserializer: DeserializationStrategy<T?>): T? {
//
//println("decodeNullableSerializableValue: ${deserializer::class.qualifiedName}")
println("decodeNullableSerializableValue: ${deserializer::class.qualifiedName}")
if (deserializer is NullReader) {
return null
}
@ -419,13 +467,13 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
return null
}
}
when (deserializer.descriptor) {
ByteArraySerializer.descriptor -> {
when {
deserializer.descriptor == ByteArraySerializer().descriptor -> {
val tag = popTag()
return if (isTagMissing(tag)) input.readByteArrayOrNull(tag) as? T
else input.readByteArray(tag) as T
}
is ListLikeDescriptor -> {
deserializer.descriptor.kind == StructureKind.LIST -> {
if (deserializer is ReferenceArraySerializer<*, *>
&& (deserializer as ListLikeSerializer<Any?, T, Any?>).typeParams.isNotEmpty()
&& (deserializer as ListLikeSerializer<Any?, T, Any?>).typeParams[0] is ByteSerializer
@ -453,15 +501,17 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
}
error("UNREACHABLE CODE")
}
is MapLikeDescriptor -> {
deserializer.descriptor.kind == StructureKind.MAP -> {
val tag = popTag()
@Suppress("SENSELESS_COMPARISON")
if (input.skipToTagOrNull(tag) { head ->
check(head.type == MAP) { "type mismatch: ${head.type}" }
// 将 mapOf(k1 to v1, k2 to v2, ...) 转换为 listOf(k1, v1, k2, v2, ...) 以便于写入.
val serializer = (deserializer as MapLikeSerializer<Any?, Any?, T, *>)
val mapEntrySerial = MapEntrySerializer(serializer.keySerializer, serializer.valueSerializer)
val setOfEntries = HashSetSerializer(mapEntrySerial).deserialize(JceMapReader(input.readInt(0), input))
val mapEntrySerial =
MapEntrySerializer(serializer.keySerializer, serializer.valueSerializer)
val setOfEntries =
SetSerializer(mapEntrySerial).deserialize(JceMapReader(input.readInt(0), input))
return setOfEntries.associateBy({ it.key }, { it.value }) as T
} == null) {
if (isTagMissing(tag)) {
@ -472,7 +522,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
}
}
if (deserializer.descriptor.kind == StructureKind.CLASS || deserializer.descriptor.kind == UnionKind.OBJECT) {
if (deserializer.descriptor.kind == StructureKind.CLASS || deserializer.descriptor.kind == StructureKind.OBJECT) {
val tag = currentTagOrNull
if (tag != null) {
@Suppress("SENSELESS_COMPARISON") // 推断 bug
@ -515,7 +565,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
}
@UseExperimental(ExperimentalUnsignedTypes::class)
@OptIn(ExperimentalUnsignedTypes::class)
internal inner class JceInput(
@PublishedApi
internal val input: ByteReadPacket,
@ -556,22 +606,38 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
}
tag = readUByte().toUInt()
}
currentJceHead = JceHead(tag = tag.toInt(), type = type.toByte())
currentJceHead = JceHead(
tag = tag.toInt(),
type = type.toByte()
)
// println("doReadHead: $currentJceHead")
return currentJceHead
}
fun readBoolean(tag: Int): Boolean = readBooleanOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readByte(tag: Int): Byte = readByteOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readShort(tag: Int): Short = readShortOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readBoolean(tag: Int): Boolean =
readBooleanOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readByte(tag: Int): Byte =
readByteOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readShort(tag: Int): Short =
readShortOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readInt(tag: Int): Int = readIntOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readLong(tag: Int): Long = readLongOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readFloat(tag: Int): Float = readFloatOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readDouble(tag: Int): Double = readDoubleOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readLong(tag: Int): Long =
readLongOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readString(tag: Int): String = readStringOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readFloat(tag: Int): Float =
readFloatOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readByteArray(tag: Int): ByteArray = readByteArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readDouble(tag: Int): Double =
readDoubleOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readString(tag: Int): String =
readStringOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readByteArray(tag: Int): ByteArray =
readByteArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
fun readByteArrayOrNull(tag: Int): ByteArray? = skipToTagOrNull(tag) {
when (it.type) {
@ -667,7 +733,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
} while (head.type.toInt() != 11)
}
@UseExperimental(ExperimentalUnsignedTypes::class)
@OptIn(ExperimentalUnsignedTypes::class)
@PublishedApi
internal fun skipField(type: Byte) = when (type.toInt()) {
0 -> this.input.discardExact(1)
@ -704,10 +770,10 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
@Suppress("MemberVisibilityCanBePrivate")
companion object {
val UTF8 = Jce(JceCharset.UTF8)
val GBK = Jce(JceCharset.GBK)
val UTF8 = JceOld(JceCharset.UTF8)
val GBK = JceOld(JceCharset.GBK)
fun byCharSet(c: JceCharset): Jce {
fun byCharSet(c: JceCharset): JceOld {
return if (c == JceCharset.UTF8) {
UTF8
} else {
@ -715,24 +781,9 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
}
}
internal const val BYTE: Byte = 0
internal const val DOUBLE: Byte = 5
internal const val FLOAT: Byte = 4
internal const val INT: Byte = 2
internal const val JCE_MAX_STRING_LENGTH = 104857600
internal const val LIST: Byte = 9
internal const val LONG: Byte = 3
internal const val MAP: Byte = 8
internal const val SHORT: Byte = 1
internal const val SIMPLE_LIST: Byte = 13
internal const val STRING1: Byte = 6
internal const val STRING4: Byte = 7
internal const val STRUCT_BEGIN: Byte = 10
internal const val STRUCT_END: Byte = 11
internal const val ZERO_TYPE: Byte = 12
private fun Any?.getClassName(): String =
(if (this == null) Unit::class else this::class).qualifiedName?.split(".")?.takeLast(2)?.joinToString(".") ?: "<unnamed class>"
(if (this == null) Unit::class else this::class).qualifiedName?.split(".")?.takeLast(2)?.joinToString(".")
?: "<unnamed class>"
}
fun <T> dumpAsPacket(serializer: SerializationStrategy<T>, obj: T): ByteReadPacket {
@ -742,14 +793,18 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
return encoder.build()
}
override fun <T> dump(serializer: SerializationStrategy<T>, obj: T): ByteArray {
return dumpAsPacket(serializer, obj).readBytes()
override fun <T> dump(serializer: SerializationStrategy<T>, value: T): ByteArray {
return dumpAsPacket(serializer, value).readBytes()
}
/**
* 注意 close [packet]!!
*/
fun <T> load(deserializer: DeserializationStrategy<T>, packet: ByteReadPacket, length: Int = packet.remaining.toInt()): T {
fun <T> load(
deserializer: DeserializationStrategy<T>,
packet: ByteReadPacket,
length: Int = packet.remaining.toInt()
): T {
return JceDecoder(JceInput(packet, length.toLong())).decode(deserializer)
}
@ -761,7 +816,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
}
}
internal inline fun <R> Jce.JceInput.skipToTagOrNull(tag: Int, block: (JceHead) -> R): R? {
internal inline fun <R> JceOld.JceInput.skipToTagOrNull(tag: Int, block: (JceHead) -> R): R? {
// println("skipping to $tag start")
while (true) {
if (isEndOfInput) { // 读不了了
@ -792,33 +847,4 @@ internal inline fun <R> Jce.JceInput.skipToTagOrNull(tag: Int, block: (JceHead)
this.skipField(head.type)
currentJceHead = readHeadOrNull()
}
}
@UseExperimental(ExperimentalUnsignedTypes::class)
inline class JceHead(private val value: Long) {
constructor(tag: Int, type: Byte) : this(tag.toLong().shl(32) or type.toLong())
val tag: Int get() = (value ushr 32).toInt()
val type: Byte get() = value.toUInt().toByte()
override fun toString(): String {
val typeString = when (type) {
Jce.BYTE -> "Byte"
Jce.DOUBLE -> "Double"
Jce.FLOAT -> "Float"
Jce.INT -> "Int"
Jce.LIST -> "List"
Jce.LONG -> "Long"
Jce.MAP -> "Map"
Jce.SHORT -> "Short"
Jce.SIMPLE_LIST -> "SimpleList"
Jce.STRING1 -> "String1"
Jce.STRING4 -> "String4"
Jce.STRUCT_BEGIN -> "StructBegin"
Jce.STRUCT_END -> "StructEnd"
Jce.ZERO_TYPE -> "Zero"
else -> error("unreachable")
}
return "JceHead(tag=$tag, type=$type($typeString))"
}
}

View File

@ -5,11 +5,19 @@
* Some code changed by Mamoe is annotated around "MIRAI MODIFY START" and "MIRAI MODIFY END"
*/
@file:Suppress("DEPRECATION_ERROR")
package net.mamoe.mirai.qqandroid.io.serialization
import kotlinx.io.*
import kotlinx.io.ByteArrayOutputStream
import kotlinx.io.ByteBuffer
import kotlinx.io.ByteOrder
import kotlinx.serialization.*
import kotlinx.serialization.internal.*
import kotlinx.serialization.builtins.ByteArraySerializer
import kotlinx.serialization.builtins.MapEntrySerializer
import kotlinx.serialization.builtins.SetSerializer
import kotlinx.serialization.internal.MapLikeSerializer
import kotlinx.serialization.internal.TaggedEncoder
import kotlinx.serialization.modules.EmptyModule
import kotlinx.serialization.modules.SerialModule
import kotlinx.serialization.protobuf.ProtoBuf
@ -33,15 +41,19 @@ internal fun extractParameters(desc: SerialDescriptor, index: Int, zeroBasedDefa
*
* 代码复制自 kotlinx.serialization. 修改部分已进行标注 (详见 "MIRAI MODIFY START")
*/
class ProtoBufWithNullableSupport(context: SerialModule = EmptyModule) : AbstractSerialFormat(context), BinaryFormat {
@OptIn(InternalSerializationApi::class)
class ProtoBufWithNullableSupport(override val context: SerialModule = EmptyModule) : SerialFormat, BinaryFormat {
internal open inner class ProtobufWriter(val encoder: ProtobufEncoder) : TaggedEncoder<ProtoDesc>() {
public override val context
internal open inner class ProtobufWriter(private val encoder: ProtobufEncoder) : TaggedEncoder<ProtoDesc>() {
override val context
get() = this@ProtoBufWithNullableSupport.context
override fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeEncoder = when (desc.kind) {
override fun beginStructure(
descriptor: SerialDescriptor,
vararg typeSerializers: KSerializer<*>
): CompositeEncoder = when (descriptor.kind) {
StructureKind.LIST -> RepeatedWriter(encoder, currentTag)
StructureKind.CLASS, UnionKind.OBJECT, is PolymorphicKind -> ObjectWriter(currentTagOrNull, encoder)
StructureKind.CLASS, StructureKind.OBJECT, is PolymorphicKind -> ObjectWriter(currentTagOrNull, encoder)
StructureKind.MAP -> MapRepeatedWriter(currentTagOrNull, encoder)
else -> throw SerializationException("Primitives are not supported at top-level")
}
@ -82,12 +94,15 @@ class ProtoBufWithNullableSupport(context: SerialModule = EmptyModule) : Abstrac
@Suppress("UNCHECKED_CAST", "NAME_SHADOWING")
override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) = when {
// encode maps as collection of map entries, not merged collection of key-values
serializer.descriptor is MapLikeDescriptor -> {
serializer.descriptor.kind == StructureKind.MAP -> {
val serializer = (serializer as MapLikeSerializer<Any?, Any?, T, *>)
val mapEntrySerial = MapEntrySerializer(serializer.keySerializer, serializer.valueSerializer)
HashSetSerializer(mapEntrySerial).serialize(this, (value as Map<*, *>).entries)
SetSerializer(mapEntrySerial).serialize(this, (value as Map<*, *>).entries)
}
serializer.descriptor == ByteArraySerializer.descriptor -> encoder.writeBytes(value as ByteArray, popTag().first)
serializer.descriptor == ByteArraySerializer().descriptor -> encoder.writeBytes(
value as ByteArray,
popTag().first
)
else -> serializer.serialize(this, value)
}
}
@ -96,7 +111,7 @@ class ProtoBufWithNullableSupport(context: SerialModule = EmptyModule) : Abstrac
val parentTag: ProtoDesc?, private val parentEncoder: ProtobufEncoder,
private val stream: ByteArrayOutputStream = ByteArrayOutputStream()
) : ProtobufWriter(ProtobufEncoder(stream)) {
override fun endEncode(desc: SerialDescriptor) {
override fun endEncode(descriptor: SerialDescriptor) {
if (parentTag != null) {
parentEncoder.writeBytes(stream.toByteArray(), parentTag.first)
} else {
@ -111,7 +126,8 @@ class ProtoBufWithNullableSupport(context: SerialModule = EmptyModule) : Abstrac
else 2 to (parentTag?.second ?: ProtoNumberType.DEFAULT)
}
internal inner class RepeatedWriter(encoder: ProtobufEncoder, val curTag: ProtoDesc) : ProtobufWriter(encoder) {
internal inner class RepeatedWriter(encoder: ProtobufEncoder, private val curTag: ProtoDesc) :
ProtobufWriter(encoder) {
override fun SerialDescriptor.getTag(index: Int) = curTag
}
@ -141,8 +157,9 @@ class ProtoBufWithNullableSupport(context: SerialModule = EmptyModule) : Abstrac
out.write(content)
}
@OptIn(ExperimentalStdlibApi::class)
fun writeString(value: String, tag: Int) {
val bytes = value.toUtf8Bytes()
val bytes = value.encodeToByteArray()
writeBytes(bytes, tag)
}
@ -228,17 +245,17 @@ class ProtoBufWithNullableSupport(context: SerialModule = EmptyModule) : Abstrac
internal const val SIZE_DELIMITED = 2
internal const val i32 = 5
val plain = ProtoBufWithNullableSupport()
private val plain = ProtoBufWithNullableSupport()
override fun <T> dump(serializer: SerializationStrategy<T>, obj: T): ByteArray = plain.dump(serializer, obj)
override fun <T> load(deserializer: DeserializationStrategy<T>, bytes: ByteArray): T = plain.load(deserializer, bytes)
override fun install(module: SerialModule) = throw IllegalStateException("You should not install anything to global instance")
override fun <T> dump(serializer: SerializationStrategy<T>, value: T): ByteArray = plain.dump(serializer, value)
override fun <T> load(deserializer: DeserializationStrategy<T>, bytes: ByteArray): T =
plain.load(deserializer, bytes)
}
override fun <T> dump(serializer: SerializationStrategy<T>, obj: T): ByteArray {
override fun <T> dump(serializer: SerializationStrategy<T>, value: T): ByteArray {
val encoder = ByteArrayOutputStream()
val dumper = ProtobufWriter(ProtobufEncoder(encoder))
dumper.encode(serializer, obj)
dumper.encode(serializer, value)
return encoder.toByteArray()
}
@ -248,20 +265,3 @@ class ProtoBufWithNullableSupport(context: SerialModule = EmptyModule) : Abstrac
}
internal fun InputStream.readExactNBytes(bytes: Int): ByteArray {
val array = ByteArray(bytes)
var read = 0
while (read < bytes) {
val i = this.read(array, read, bytes - read)
if (i == -1) throw IOException("Unexpected EOF")
read += i
}
return array
}
internal fun InputStream.readToByteBuffer(bytes: Int): ByteBuffer {
val arr = readExactNBytes(bytes)
val buf = ByteBuffer.allocate(bytes)
buf.put(arr).flip()
return buf
}

View File

@ -0,0 +1,272 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("PrivatePropertyName")
package net.mamoe.mirai.qqandroid.io.serialization.jce
import kotlinx.serialization.*
import kotlinx.serialization.builtins.AbstractDecoder
import kotlinx.serialization.internal.TaggedDecoder
import kotlinx.serialization.modules.SerialModule
@OptIn(InternalSerializationApi::class) // 将来 kotlinx 修改后再复制过来 mirai.
internal class JceDecoder(
val jce: JceInput, override val context: SerialModule
) : TaggedDecoder<JceTag>() {
override val updateMode: UpdateMode
get() = UpdateMode.BANNED
override fun SerialDescriptor.getTag(index: Int): JceTag {
val annotations = this.getElementAnnotations(index)
val id = annotations.filterIsInstance<JceId>().single().id
// ?: error("cannot find @JceId or @ProtoId for ${this.getElementName(index)} in ${this.serialName}")
//println("getTag: ${this.getElementName(index)}=$id")
return JceTagCommon(id)
}
private fun SerialDescriptor.getJceTagId(index: Int): Int {
//println("getTag: ${getElementName(index)}")
return getElementAnnotations(index).filterIsInstance<JceId>().singleOrNull()?.id
?: error("missing @JceId for ${getElementName(index)} in ${this.serialName}")
}
private val SimpleByteArrayReader: SimpleByteArrayReaderImpl = SimpleByteArrayReaderImpl()
private inner class SimpleByteArrayReaderImpl : AbstractDecoder() {
override fun decodeSequentially(): Boolean = true
override fun endStructure(descriptor: SerialDescriptor) {
this@JceDecoder.endStructure(descriptor)
}
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
this@JceDecoder.pushTag(JceTagListElement)
return this@JceDecoder.beginStructure(descriptor, *typeParams)
}
override fun decodeByte(): Byte = jce.input.readByte()
override fun decodeShort(): Short = error("illegal access")
override fun decodeInt(): Int = error("illegal access")
override fun decodeLong(): Long = error("illegal access")
override fun decodeFloat(): Float = error("illegal access")
override fun decodeDouble(): Double = error("illegal access")
override fun decodeBoolean(): Boolean = error("illegal access")
override fun decodeChar(): Char = error("illegal access")
override fun decodeEnum(enumDescriptor: SerialDescriptor): Int = error("illegal access")
override fun decodeString(): String = error("illegal access")
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
error("should not be reached")
}
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
// 不要读下一个 head
return jce.currentHead.let { jce.readJceIntValue(it) }
}
}
private val ListReader: ListReaderImpl = ListReaderImpl()
private inner class ListReaderImpl : AbstractDecoder() {
override fun decodeSequentially(): Boolean = true
override fun decodeElementIndex(descriptor: SerialDescriptor): Int = error("should not be reached")
override fun endStructure(descriptor: SerialDescriptor) {
this@JceDecoder.endStructure(descriptor)
}
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
this@JceDecoder.pushTag(JceTagListElement)
return this@JceDecoder.beginStructure(descriptor, *typeParams)
}
override fun decodeByte(): Byte = jce.useHead { jce.readJceByteValue(it) }
override fun decodeShort(): Short = jce.useHead { jce.readJceShortValue(it) }
override fun decodeInt(): Int = jce.useHead { jce.readJceIntValue(it) }
override fun decodeLong(): Long = jce.useHead { jce.readJceLongValue(it) }
override fun decodeFloat(): Float = jce.useHead { jce.readJceFloatValue(it) }
override fun decodeDouble(): Double = jce.useHead { jce.readJceDoubleValue(it) }
override fun decodeBoolean(): Boolean = jce.useHead { jce.readJceBooleanValue(it) }
override fun decodeChar(): Char = decodeByte().toChar()
override fun decodeEnum(enumDescriptor: SerialDescriptor): Int = decodeInt()
override fun decodeString(): String = jce.useHead { jce.readJceStringValue(it) }
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
//println("decodeCollectionSize: ${descriptor.serialName}")
// 不读下一个 head
return jce.useHead { jce.readJceIntValue(it) }
}
}
private val MapReader: MapReaderImpl = MapReaderImpl()
private inner class MapReaderImpl : AbstractDecoder() {
override fun decodeSequentially(): Boolean = true
override fun decodeElementIndex(descriptor: SerialDescriptor): Int = error("stub")
override fun endStructure(descriptor: SerialDescriptor) {
this@JceDecoder.endStructure(descriptor)
}
private var state: Boolean = true
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
this@JceDecoder.pushTag(if (jce.currentHead.tag == 0) JceTagMapEntryKey else JceTagMapEntryValue)
state = !state
return this@JceDecoder.beginStructure(descriptor, *typeParams)
}
override fun decodeByte(): Byte = jce.useHead { jce.readJceByteValue(it) }
override fun decodeShort(): Short = jce.useHead { jce.readJceShortValue(it) }
override fun decodeInt(): Int = jce.useHead { jce.readJceIntValue(it) }
override fun decodeLong(): Long = jce.useHead { jce.readJceLongValue(it) }
override fun decodeFloat(): Float = jce.useHead { jce.readJceFloatValue(it) }
override fun decodeDouble(): Double = jce.useHead { jce.readJceDoubleValue(it) }
override fun decodeBoolean(): Boolean = jce.useHead { jce.readJceBooleanValue(it) }
override fun decodeChar(): Char = decodeByte().toChar()
override fun decodeEnum(enumDescriptor: SerialDescriptor): Int = decodeInt()
override fun decodeString(): String = jce.useHead { jce.readJceStringValue(it) }
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
//println("decodeCollectionSize in MapReader: ${descriptor.serialName}")
// 不读下一个 head
return jce.useHead { jce.readJceIntValue(it) }
}
}
override fun endStructure(descriptor: SerialDescriptor) {
//println("endStructure: $descriptor")
if (currentTagOrNull?.isSimpleByteArray == true) {
jce.prepareNextHead() // read to next head
}
if (descriptor.kind == StructureKind.CLASS) {
if (currentTagOrNull == null) {
return
}
while (true) {
val currentHead = jce.currentHeadOrNull ?: return
if (currentHead.type == Jce.STRUCT_END) {
jce.prepareNextHead()
//println("current end")
break
}
//println("current $currentHead")
jce.skipField(currentHead.type)
jce.prepareNextHead()
}
// pushTag(JceTag(0, true))
// skip STRUCT_END
// popTag()
}
}
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
//println()
//println("beginStructure: ${descriptor.serialName}")
return when (descriptor.kind) {
is PrimitiveKind -> this@JceDecoder
StructureKind.MAP -> {
//println("!! MAP")
return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) {
it.checkType(Jce.MAP)
MapReader
}
}
StructureKind.LIST -> {
//println("!! ByteArray")
//println("decoderTag: $currentTagOrNull")
//println("jceHead: " + jce.currentHeadOrNull)
return jce.skipToHeadAndUseIfPossibleOrFail(currentTag.id) {
//println("listHead: $it")
when (it.type) {
Jce.SIMPLE_LIST -> {
currentTag.isSimpleByteArray = true
jce.prepareNextHead() // 无用的元素类型
SimpleByteArrayReader
}
Jce.LIST -> ListReader
else -> error("type mismatch. Expected SIMPLE_LIST or LIST, got ${it.type} instead")
}
}
}
StructureKind.CLASS -> {
currentTagOrNull ?: return this@JceDecoder // outermost
//println("!! CLASS")
//println("decoderTag: $currentTag")
//println("jceHead: " + jce.currentHeadOrNull)
return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) { jceHead ->
jceHead.checkType(Jce.STRUCT_BEGIN)
repeat(descriptor.elementsCount) {
pushTag(descriptor.getTag(descriptor.elementsCount - it - 1)) // better performance
}
this // independent tag stack
}
}
StructureKind.OBJECT -> error("unsupported StructureKind.OBJECT: ${descriptor.serialName}")
is UnionKind -> error("unsupported UnionKind: ${descriptor.serialName}")
is PolymorphicKind -> error("unsupported PolymorphicKind: ${descriptor.serialName}")
}
}
override fun decodeSequentially(): Boolean = false
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
val jceHead = jce.currentHeadOrNull ?: return CompositeDecoder.READ_DONE
if (jceHead.type == Jce.STRUCT_END) {
return CompositeDecoder.READ_DONE
}
repeat(descriptor.elementsCount) {
val tag = descriptor.getJceTagId(it)
if (tag == jceHead.tag) {
return it
}
}
return CompositeDecoder.READ_DONE // optional support
}
override fun decodeTaggedInt(tag: JceTag): Int =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceIntValue(it) }
override fun decodeTaggedByte(tag: JceTag): Byte =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceByteValue(it) }
override fun decodeTaggedBoolean(tag: JceTag): Boolean =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceBooleanValue(it) }
override fun decodeTaggedFloat(tag: JceTag): Float =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceFloatValue(it) }
override fun decodeTaggedDouble(tag: JceTag): Double =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceDoubleValue(it) }
override fun decodeTaggedShort(tag: JceTag): Short =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceShortValue(it) }
override fun decodeTaggedLong(tag: JceTag): Long =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceLongValue(it) }
override fun decodeTaggedString(tag: JceTag): String =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceStringValue(it) }
override fun decodeTaggedNotNullMark(tag: JceTag): Boolean {
return jce.skipToHeadOrNull(tag.id) != null
}
}

View File

@ -0,0 +1,241 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.qqandroid.io.serialization.jce
import kotlinx.io.core.*
import net.mamoe.mirai.qqandroid.io.serialization.JceCharset
import net.mamoe.mirai.utils.io.readString
/**
* Jce Input. 需要手动管理 head.
*/
internal class JceInput(
val input: Input, val charset: JceCharset
) {
private var _head: JceHead? = null
val currentHead: JceHead get() = _head ?: throw EOFException("No current JceHead available")
val currentHeadOrNull: JceHead? get() = _head
init {
prepareNextHead()
}
/**
* 读取下一个 [JceHead] 并保存. 可通过 [currentHead] 获取这个 [JceHead].
*
* @return 是否成功读取. 返回 `false` 时代表 [Input.endOfInput]
*/
fun prepareNextHead(): Boolean {
return readNextHeadButDoNotAssignTo_Head().also { _head = it; } != null
}
fun nextHead(): JceHead {
if (!prepareNextHead()) {
throw EOFException("No more JceHead available")
}
return currentHead
}
/**
* 直接读取下一个 [JceHead] 并返回.
* 返回 `null` 则代表 [Input.endOfInput]
*/
@Suppress("FunctionName")
@OptIn(ExperimentalUnsignedTypes::class)
private fun readNextHeadButDoNotAssignTo_Head(): JceHead? {
if (input.endOfInput) {
return null
}
val var2 = input.readUByte()
val type = var2 and 15u
var tag = var2.toUInt() shr 4
if (tag == 15u) {
tag = input.readUByte().toUInt()
}
return JceHead(
tag = tag.toInt(),
type = type.toByte()
)
}
/**
* 使用这个 [JceHead].
* [block] 结束后将会 [准备下一个 [JceHead]][prepareNextHead]
*/
inline fun <R> useHead(crossinline block: (JceHead) -> R): R {
return currentHead.let(block).also { prepareNextHead() }
}
/**
* 跳过 [JceHead] 和对应的数据值, 直到找到 [tag], 否则返回 `null`
*/
inline fun <R> skipToHeadAndUseIfPossibleOrNull(tag: Int, crossinline block: (JceHead) -> R): R? {
return skipToHeadOrNull(tag)?.let(block).also { prepareNextHead() }
}
/**
* 跳过 [JceHead] 和对应的数据值, 直到找到 [tag], 否则抛出异常
*/
inline fun <R : Any> skipToHeadAndUseIfPossibleOrFail(
tag: Int,
crossinline message: () -> String = { "tag not found: $tag" },
crossinline block: (JceHead) -> R
): R {
return checkNotNull<R>(skipToHeadAndUseIfPossibleOrNull(tag, block), message)
}
tailrec fun skipToHeadOrNull(tag: Int): JceHead? {
val current: JceHead = currentHeadOrNull ?: return null // no backing field
return when {
current.tag > tag -> null // tag 大了,即找不到
current.tag == tag -> current // 满足需要.
else -> { // tag 小了
skipField(current.type)
check(prepareNextHead()) { "cannot skip to tag $tag, early EOF" }
skipToHeadOrNull(tag)
}
}
}
inline fun skipToHeadOrFail(
tag: Int,
message: () -> String = { "head not found: $tag" }
): JceHead {
return checkNotNull(skipToHeadOrNull(tag), message)
}
@OptIn(ExperimentalUnsignedTypes::class)
@PublishedApi
internal fun skipField(type: Byte): Unit = when (type) {
Jce.BYTE -> this.input.discardExact(1)
Jce.SHORT -> this.input.discardExact(2)
Jce.INT -> this.input.discardExact(4)
Jce.LONG -> this.input.discardExact(8)
Jce.FLOAT -> this.input.discardExact(4)
Jce.DOUBLE -> this.input.discardExact(8)
Jce.STRING1 -> this.input.discardExact(this.input.readUByte().toInt())
Jce.STRING4 -> this.input.discardExact(this.input.readInt())
Jce.MAP -> { // map
repeat(skipToHeadAndUseIfPossibleOrFail(0) {
readJceIntValue(it)
} * 2) {
useHead { skipField(it.type) }
}
}
Jce.LIST -> { // list
repeat(skipToHeadAndUseIfPossibleOrFail(0) {
readJceIntValue(it)
}) {
useHead { skipField(it.type) }
}
}
Jce.STRUCT_BEGIN -> {
fun skipToStructEnd() {
var head: JceHead
do {
head = nextHead()
skipField(head.type)
} while (head.type.toInt() != 11)
}
skipToStructEnd()
}
Jce.STRUCT_END, Jce.ZERO_TYPE -> {
}
Jce.SIMPLE_LIST -> {
val head = nextHead()
check(head.type.toInt() == 0) { "skipField with invalid type, type value: " + type + ", " + head.type }
this.input.discardExact(
skipToHeadAndUseIfPossibleOrFail(0) {
readJceIntValue(it)
}
)
}
else -> error("invalid type: $type")
}
// region readers
fun readJceIntValue(head: JceHead): Int {
//println("readJceIntValue: $head")
return when (head.type) {
Jce.ZERO_TYPE -> 0
Jce.BYTE -> input.readByte().toInt()
Jce.SHORT -> input.readShort().toInt()
Jce.INT -> input.readInt()
else -> error("type mismatch: ${head.type}")
}
}
fun readJceShortValue(head: JceHead): Short {
return when (head.type) {
Jce.ZERO_TYPE -> 0
Jce.BYTE -> input.readByte().toShort()
Jce.SHORT -> input.readShort()
else -> error("type mismatch: ${head.type}")
}
}
fun readJceLongValue(head: JceHead): Long {
return when (head.type) {
Jce.ZERO_TYPE -> 0
Jce.BYTE -> input.readByte().toLong()
Jce.SHORT -> input.readShort().toLong()
Jce.INT -> input.readInt().toLong()
Jce.LONG -> input.readLong()
else -> error("type mismatch ${head.type}")
}
}
fun readJceByteValue(head: JceHead): Byte {
//println("readJceByteValue: $head")
return when (head.type) {
Jce.ZERO_TYPE -> 0
Jce.BYTE -> input.readByte()
else -> error("type mismatch: ${head.type}")
}
}
fun readJceFloatValue(head: JceHead): Float {
return when (head.type) {
Jce.ZERO_TYPE -> 0f
Jce.FLOAT -> input.readFloat()
else -> error("type mismatch: ${head.type}")
}
}
@OptIn(ExperimentalUnsignedTypes::class)
fun readJceStringValue(head: JceHead): String {
//println("readJceStringValue: $head")
return when (head.type) {
Jce.STRING1 -> input.readString(input.readUByte().toInt(), charset = charset.kotlinCharset)
Jce.STRING4 -> input.readString(
input.readUInt().toInt().also { require(it in 1 until 104857600) { "bad string length: $it" } },
charset = charset.kotlinCharset
)
else -> error("type mismatch: ${head.type}, expecting 6 or 7 (for string)")
}
}
fun readJceDoubleValue(head: JceHead): Double {
return when (head.type.toInt()) {
12 -> 0.0
4 -> input.readFloat().toDouble()
5 -> input.readDouble()
else -> error("type mismatch: ${head.type}")
}
}
fun readJceBooleanValue(head: JceHead): Boolean {
return readJceByteValue(head) == 1.toByte()
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.qqandroid.io.serialization.jce
import kotlinx.io.core.*
import kotlinx.serialization.BinaryFormat
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialFormat
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.modules.EmptyModule
import kotlinx.serialization.modules.SerialModule
import net.mamoe.mirai.qqandroid.io.serialization.IOFormat
import net.mamoe.mirai.qqandroid.io.serialization.JceCharset
import net.mamoe.mirai.qqandroid.io.serialization.JceOld
import net.mamoe.mirai.utils.io.toReadPacket
/**
* Jce 数据结构序列化和反序列化器.
*
* @author Him188
*/
class Jce(
override val context: SerialModule,
val charset: JceCharset
) : SerialFormat, IOFormat, BinaryFormat {
override fun <T> dumpTo(serializer: SerializationStrategy<T>, ojb: T, output: Output) {
output.writePacket(JceOld.byCharSet(this.charset).dumpAsPacket(serializer, ojb))
}
override fun <T> load(deserializer: DeserializationStrategy<T>, input: Input): T {
return JceDecoder(JceInput(input, charset), context).decodeSerializableValue(deserializer)
}
override fun <T> dump(serializer: SerializationStrategy<T>, value: T): ByteArray {
return buildPacket { dumpTo(serializer, value, this) }.readBytes()
}
override fun <T> load(deserializer: DeserializationStrategy<T>, bytes: ByteArray): T {
return load(deserializer, bytes.toReadPacket())
}
companion object {
val UTF_8 = Jce(EmptyModule, JceCharset.UTF8)
val GBK = Jce(EmptyModule, JceCharset.GBK)
fun byCharSet(c: JceCharset): Jce {
return if (c == JceCharset.UTF8) UTF_8 else GBK
}
internal const val BYTE: Byte = 0
internal const val DOUBLE: Byte = 5
internal const val FLOAT: Byte = 4
internal const val INT: Byte = 2
internal const val JCE_MAX_STRING_LENGTH = 104857600
internal const val LIST: Byte = 9
internal const val LONG: Byte = 3
internal const val MAP: Byte = 8
internal const val SHORT: Byte = 1
internal const val SIMPLE_LIST: Byte = 13
internal const val STRING1: Byte = 6
internal const val STRING4: Byte = 7
internal const val STRUCT_BEGIN: Byte = 10
internal const val STRUCT_END: Byte = 11
internal const val ZERO_TYPE: Byte = 12
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.qqandroid.io.serialization.jce
import kotlinx.io.core.Output
import kotlinx.serialization.SerialInfo
/**
* 标注 JCE 序列化时使用的 ID
*/
@SerialInfo
@Target(AnnotationTarget.PROPERTY)
annotation class JceId(val id: Int)
/**
* 类中元素的 tag
*
* 保留这个结构, 为将来增加功能的兼容性.
*/
@PublishedApi
internal abstract class JceTag {
abstract val id: Int
internal var isSimpleByteArray: Boolean = false
}
internal object JceTagListElement : JceTag() {
override val id: Int get() = 0
override fun toString(): String {
return "JceTagListElement"
}
}
internal object JceTagMapEntryKey : JceTag() {
override val id: Int get() = 0
override fun toString(): String {
return "JceTagMapEntryKey"
}
}
internal object JceTagMapEntryValue : JceTag() {
override val id: Int get() = 1
override fun toString(): String {
return "JceTagMapEntryValue"
}
}
internal data class JceTagCommon(
override val id: Int
) : JceTag()
fun JceHead.checkType(type: Byte) {
check(this.type == type) { "type mismatch. Expected $type, actual ${this.type}" }
}
@PublishedApi
internal fun Output.writeJceHead(type: Byte, tag: Int) {
if (tag < 15) {
writeByte(((tag shl 4) or type.toInt()).toByte())
return
}
if (tag < 256) {
writeByte((type.toInt() or 0xF0).toByte())
writeByte(tag.toByte())
return
}
error("tag is too large: $tag")
}
@OptIn(ExperimentalUnsignedTypes::class)
inline class JceHead(private val value: Long) {
constructor(tag: Int, type: Byte) : this(tag.toLong().shl(32) or type.toLong())
val tag: Int get() = (value ushr 32).toInt()
val type: Byte get() = value.toUInt().toByte()
override fun toString(): String {
val typeString = when (type) {
Jce.BYTE -> "Byte"
Jce.DOUBLE -> "Double"
Jce.FLOAT -> "Float"
Jce.INT -> "Int"
Jce.LIST -> "List"
Jce.LONG -> "Long"
Jce.MAP -> "Map"
Jce.SHORT -> "Short"
Jce.SIMPLE_LIST -> "SimpleList"
Jce.STRING1 -> "String1"
Jce.STRING4 -> "String4"
Jce.STRUCT_BEGIN -> "StructBegin"
Jce.STRUCT_END -> "StructEnd"
Jce.ZERO_TYPE -> "Zero"
else -> error("illegal jce type: $type")
}
return "JceHead(tag=$tag, type=$type($typeString))"
}
}

View File

@ -12,30 +12,35 @@
package net.mamoe.mirai.qqandroid.io.serialization
import io.ktor.utils.io.core.BytePacketBuilder
import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.readBytes
import io.ktor.utils.io.core.writeFully
import kotlinx.io.core.*
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialDescriptor
import kotlinx.serialization.SerializationStrategy
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestDataVersion2
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestDataVersion3
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.firstValue
import net.mamoe.mirai.utils.io.read
import net.mamoe.mirai.utils.io.readPacketExact
import net.mamoe.mirai.utils.io.toReadPacket
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
fun <T : JceStruct> ByteArray.loadAs(deserializer: DeserializationStrategy<T>, c: JceCharset = JceCharset.UTF8): T {
return Jce.byCharSet(c).load(deserializer, this)
return Jce.byCharSet(c).load(deserializer, this.toReadPacket())
}
fun <T : JceStruct> BytePacketBuilder.writeJceStruct(serializer: SerializationStrategy<T>, struct: T, charset: JceCharset = JceCharset.GBK) {
this.writePacket(Jce.byCharSet(charset).dumpAsPacket(serializer, struct))
fun <T : JceStruct> BytePacketBuilder.writeJceStruct(
serializer: SerializationStrategy<T>,
struct: T,
charset: JceCharset = JceCharset.GBK
) {
Jce.byCharSet(charset).dumpTo(serializer, struct, this)
}
fun <T : JceStruct> ByteReadPacket.readJceStruct(
@ -43,7 +48,8 @@ fun <T : JceStruct> ByteReadPacket.readJceStruct(
charset: JceCharset = JceCharset.UTF8,
length: Int = this.remaining.toInt()
): T {
return Jce.byCharSet(charset).load(serializer, this, length)
@OptIn(MiraiInternalAPI::class)
return Jce.byCharSet(charset).load(serializer, this.readPacketExact(length))
}
/**
@ -73,18 +79,20 @@ fun <T : ProtoBuf> ByteReadPacket.decodeUniPacket(deserializer: DeserializationS
fun <R> ByteReadPacket.decodeUniRequestPacketAndDeserialize(name: String? = null, block: (ByteArray) -> R): R {
val request = this.readJceStruct(RequestPacket.serializer())
return block(if (name == null) when (request.iVersion.toInt()) {
return block(if (name == null) when (request.iVersion?.toInt() ?: 3) {
2 -> request.sBuffer.loadAs(RequestDataVersion2.serializer()).map.firstValue().firstValue()
3 -> request.sBuffer.loadAs(RequestDataVersion3.serializer()).map.firstValue()
else -> error("unsupported version ${request.iVersion}")
} else when (request.iVersion.toInt()) {
2 -> request.sBuffer.loadAs(RequestDataVersion2.serializer()).map.getOrElse(name) { error("cannot find $name") }.firstValue()
} else when (request.iVersion?.toInt() ?: 3) {
2 -> request.sBuffer.loadAs(RequestDataVersion2.serializer()).map.getOrElse(name) { error("cannot find $name") }
.firstValue()
3 -> request.sBuffer.loadAs(RequestDataVersion3.serializer()).map.getOrElse(name) { error("cannot find $name") }
else -> error("unsupported version ${request.iVersion}")
})
}
fun <T : JceStruct> T.toByteArray(serializer: SerializationStrategy<T>, c: JceCharset = JceCharset.GBK): ByteArray = Jce.byCharSet(c).dump(serializer, this)
fun <T : JceStruct> T.toByteArray(serializer: SerializationStrategy<T>, c: JceCharset = JceCharset.GBK): ByteArray =
Jce.byCharSet(c).dump(serializer, this)
fun <T : ProtoBuf> BytePacketBuilder.writeProtoBuf(serializer: SerializationStrategy<T>, v: T) {
this.writeFully(v.toByteArray(serializer))

View File

@ -23,6 +23,7 @@ import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.SourceMsg
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.OnlinePush
import net.mamoe.mirai.utils.MiraiExperimentalAPI
@ -40,7 +41,7 @@ internal class MessageSourceFromServer(
?: error("cannot find sequenceId from ImMsgBody.SourceMsg")).toLong().shl(32) or
delegate.pbReserve.loadAs(SourceMsg.ResvAttr.serializer()).origUids!!.and(0xFFFFFFFF)
override val toUin: Long get() = delegate.toUin
override val toUin: Long get() = delegate.toUin // always 0
override suspend fun ensureSequenceIdAvailable() {
// nothing to do
@ -118,38 +119,16 @@ internal class MessageSourceFromMsg(
}
private fun toJceDataImplForGroup(): ImMsgBody.SourceMsg {
val groupUin = Group.calculateGroupUinByGroupCode(groupId)
return ImMsgBody.SourceMsg(
origSeqs = listOf(delegate.msgHead.msgSeq),
senderUin = delegate.msgHead.fromUin,
toUin = groupUin,
toUin = 0,
flag = 1,
elems = delegate.msgBody.richText.elems,
type = 0,
time = delegate.msgHead.msgTime,
pbReserve = SourceMsg.ResvAttr(
origUids = messageRandom.toLong() and 0xffFFffFF
).toByteArray(SourceMsg.ResvAttr.serializer()),
srcMsg = MsgComm.Msg(
msgHead = MsgComm.MsgHead(
fromUin = delegate.msgHead.fromUin, // qq
toUin = groupUin, // group
msgType = delegate.msgHead.msgType, // 82?
c2cCmd = delegate.msgHead.c2cCmd,
msgSeq = delegate.msgHead.msgSeq,
msgTime = delegate.msgHead.msgTime,
msgUid = messageRandom.toLong() and 0xffFFffFF, // ok
groupInfo = MsgComm.GroupInfo(groupCode = groupId),
isSrcMsg = true
),
msgBody = ImMsgBody.MsgBody(
richText = ImMsgBody.RichText(
elems = elems
)
)
).toByteArray(MsgComm.Msg.serializer())
pbReserve = EMPTY_BYTE_ARRAY,
srcMsg = EMPTY_BYTE_ARRAY
)
}
@ -253,7 +232,7 @@ internal class MessageSourceFromSendFriend(
val sequenceId: Int,
override val originalMessage: MessageChain
) : MessageSourceFromSend() {
@UseExperimental(ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
override val id: Long
get() = sequenceId.toLong().shl(32) or
messageRandom.toLong().and(0xFFFFFFFF)
@ -277,12 +256,12 @@ internal class MessageSourceFromSendGroup(
) : MessageSourceFromSend() {
private lateinit var sequenceIdDeferred: Deferred<Int>
@UseExperimental(ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
override val id: Long
get() = sequenceIdDeferred.getCompleted().toLong().shl(32) or
messageRandom.toLong().and(0xFFFFFFFF)
@UseExperimental(MiraiExperimentalAPI::class)
@OptIn(MiraiExperimentalAPI::class)
internal fun startWaitingSequenceId(coroutineScope: CoroutineScope) {
sequenceIdDeferred =
coroutineScope.subscribingGetAsync<OnlinePush.PbPushGroupMsg.SendGroupMessageReceipt, Int>(

View File

@ -9,15 +9,14 @@
package net.mamoe.mirai.qqandroid.message
import io.ktor.utils.io.core.*
import kotlinx.io.core.*
import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.MiraiDebugAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.encodeToString
import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.read
import net.mamoe.mirai.utils.io.toByteArray
@ -219,7 +218,7 @@ private val atAllData = ImMsgBody.Elem(
)
)
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgBody.Elem> {
val elements = mutableListOf<ImMsgBody.Elem>()
@ -240,6 +239,25 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
elements.add(ImMsgBody.Elem(text = it.toJceData()))
elements.add(ImMsgBody.Elem(text = ImMsgBody.Text(str = " ")))
}
is LightApp -> elements.add(
ImMsgBody.Elem(
lightApp = ImMsgBody.LightAppElem(
data = byteArrayOf(1) + MiraiPlatformUtils.zip(it.content.toByteArray())
)
)
)
is RichMessage -> elements.add(
ImMsgBody.Elem(
richMsg = ImMsgBody.RichMsg(
serviceId = when (it) {
is XmlMessage -> 60
is JsonMessage -> 1
else -> error("unsupported RichMessage")
},
template1 = byteArrayOf(1) + MiraiPlatformUtils.zip(it.content.toByteArray())
)
)
)
is OfflineGroupImage -> elements.add(ImMsgBody.Elem(customFace = it.toJceData()))
is OnlineGroupImageImpl -> elements.add(ImMsgBody.Elem(customFace = it.delegate))
is OnlineFriendImageImpl -> elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate))
@ -249,7 +267,7 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
is QuoteReplyToSend -> {
if (forGroup) {
check(it is QuoteReplyToSend.ToGroup) {
"sending a quote to group suing QuoteReplyToSend.ToFriend"
"sending a quote to group using QuoteReplyToSend.ToFriend"
}
if (it.sender is Member) {
transformOneMessage(it.createAt())
@ -266,9 +284,10 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
}
this.forEach(::transformOneMessage)
// if(this.any<QuoteReply>()){
elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 F8 01 00 C8 02 00".hexToBytes())))
// }
if (this.any<RichMessage>()) {
// 08 09 78 00 A0 01 81 DC 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 02 08 03 90 04 80 80 80 10 B8 04 00 C0 04 00
elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "08 09 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 02 08 03 90 04 80 80 80 10 B8 04 00 C0 04 00".hexToBytes())))
} else elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 F8 01 00 C8 02 00".hexToBytes())))
return elements
}
@ -332,7 +351,7 @@ internal class OnlineFriendImageImpl(
}
}
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
@OptIn(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
internal fun MsgComm.Msg.toMessageChain(): MessageChain {
val elements = this.msgBody.richText.elems
@ -343,7 +362,7 @@ internal fun MsgComm.Msg.toMessageChain(): MessageChain {
}
// These two functions are not identical, dont combine.
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
@OptIn(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
internal fun ImMsgBody.SourceMsg.toMessageChain(): MessageChain {
val elements = this.elems!!
@ -368,7 +387,9 @@ private fun MessageChain.removeAtIfHasQuoteReply(): MessageChain =
}.asMessageChain()
} else this*/
@UseExperimental(MiraiInternalAPI::class, ExperimentalUnsignedTypes::class, MiraiDebugAPI::class, LowLevelAPI::class)
@OptIn(
MiraiInternalAPI::class, ExperimentalUnsignedTypes::class, MiraiDebugAPI::class, LowLevelAPI::class
)
internal fun List<ImMsgBody.Elem>.joinToMessageChain(message: MessageChainBuilder) {
this.forEach {
when {
@ -395,6 +416,23 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(message: MessageChainBuilde
}
}
}
it.lightApp != null -> {
val content = MiraiPlatformUtils.unzip(it.lightApp.data, 1).encodeToString()
message.add(LightApp(content))
}
it.richMsg != null -> {
val content = MiraiPlatformUtils.unzip(it.richMsg.template1, 1).encodeToString()
when (it.richMsg.serviceId) {
1 -> message.add(JsonMessage(content))
60 -> message.add(XmlMessage(content))
else -> {
@Suppress("DEPRECATION")
MiraiLogger.debug {
"unknown richMsg.serviceId: ${it.richMsg.serviceId}, content=${it.richMsg.template1.contentToString()}, \ntryUnzip=${content}"
}
}
}
}
}
}

View File

@ -9,12 +9,15 @@
package net.mamoe.mirai.qqandroid.network
import io.ktor.utils.io.core.*
import kotlinx.atomicfu.AtomicRef
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Input
import kotlinx.io.core.buildPacket
import kotlinx.io.core.use
import net.mamoe.mirai.data.MultiPacket
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.event.*
@ -45,7 +48,7 @@ import kotlin.jvm.Volatile
import kotlin.time.ExperimentalTime
@Suppress("MemberVisibilityCanBePrivate")
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler() {
override val bot: QQAndroidBot by bot.unsafeWeakRef()
override val supervisor: CompletableJob = SupervisorJob(bot.coroutineContext[Job])
@ -67,14 +70,14 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
_packetReceiverJob?.join()
return this.launch(CoroutineName("Incoming Packet Receiver")) {
while (channel.isOpen) {
while (channel.isOpen && isActive) {
val rawInput = try {
channel.read()
} catch (e: CancellationException) {
return@launch
} catch (e: Throwable) {
if (this@QQAndroidBotNetworkHandler.isActive) {
BotOfflineEvent.Dropped(bot, e).broadcast()
bot.launch { BotOfflineEvent.Dropped(bot, e).broadcast() }
}
return@launch
}
@ -141,10 +144,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
continue@mainloop
}
is WtLogin.Login.LoginPacketResponse.Captcha.Slider -> {
var ticket = bot.configuration.loginSolver.onSolveSliderCaptcha(bot, response.url)
if (ticket == null) {
ticket = ""
}
val ticket = bot.configuration.loginSolver.onSolveSliderCaptcha(bot, response.url).orEmpty()
response = WtLogin.Login.SubCommand2.SubmitSliderCaptcha(bot.client, ticket).sendAndExpect()
continue@mainloop
}
@ -183,7 +183,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
internal var pendingIncomingPackets: LockFreeLinkedList<KnownPacketFactories.IncomingPacket<*>>? =
LockFreeLinkedList()
@UseExperimental(MiraiExperimentalAPI::class, ExperimentalTime::class)
@OptIn(MiraiExperimentalAPI::class, ExperimentalTime::class)
override suspend fun init(): Unit = coroutineScope {
check(bot.isActive) { "bot is dead therefore network can't init" }
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't init" }
@ -338,6 +338,14 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
suspend fun doHeartBeat(): Exception? {
val lastException: Exception?
try {
kotlin.runCatching {
Heartbeat.Alive(bot.client)
.sendAndExpect<Heartbeat.Alive.Response>(
timeoutMillis = bot.configuration.heartbeatTimeoutMillis,
retry = 2
)
return null
}
Heartbeat.Alive(bot.client)
.sendAndExpect<Heartbeat.Alive.Response>(
timeoutMillis = bot.configuration.heartbeatTimeoutMillis,
@ -372,10 +380,17 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
*
* @param input 一个完整的包的内容, 去掉开头的 int 包长度
*/
@UseExperimental(ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
fun parsePacketAsync(input: Input): Job {
return this.launch(start = CoroutineStart.ATOMIC) {
input.use { parsePacket(it) }
return this.launch(
start = CoroutineStart.ATOMIC
) {
try {
input.use { parsePacket(it) }
} catch (e: Exception) {
// 傻逼协程吞异常
logger.error(e)
}
}
}

View File

@ -11,9 +11,9 @@
package net.mamoe.mirai.qqandroid.network
import io.ktor.utils.io.core.*
import kotlinx.atomicfu.AtomicInt
import kotlinx.atomicfu.atomic
import kotlinx.io.core.*
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.RawAccountIdUse
import net.mamoe.mirai.data.OnlineStatus
@ -40,7 +40,7 @@ import net.mamoe.mirai.utils.io.*
DOMAINS
Pskey: "openmobile.qq.com"
*/
@UseExperimental(MiraiExperimentalAPI::class, MiraiInternalAPI::class)
@OptIn(MiraiExperimentalAPI::class, MiraiInternalAPI::class)
@PublishedApi
internal open class QQAndroidClient(
context: Context,
@ -158,8 +158,8 @@ internal open class QQAndroidClient(
*/
val uin: Long get() = _uin
@UseExperimental(RawAccountIdUse::class)
@Suppress("PropertyName")
@OptIn(RawAccountIdUse::class)
@Suppress("PropertyName", "DEPRECATION_ERROR")
internal var _uin: Long = bot.account.id
var t530: ByteArray? = null
@ -191,8 +191,9 @@ internal open class QQAndroidClient(
lateinit var t104: ByteArray
}
@OptIn(MiraiInternalAPI::class)
internal fun generateTgtgtKey(guid: ByteArray): ByteArray =
md5(getRandomByteArray(16) + guid)
MiraiPlatformUtils.md5(getRandomByteArray(16) + guid)
internal class ReserveUinInfo(
@ -315,7 +316,7 @@ internal class Pt4Token(data: ByteArray, creationTime: Long, expireTime: Long) :
internal typealias PSKeyMap = MutableMap<String, PSKey>
internal typealias Pt4TokenMap = MutableMap<String, Pt4Token>
internal inline fun Input.readUShortLVString(): String = io.ktor.utils.io.core.String(this.readUShortLVByteArray())
internal inline fun Input.readUShortLVString(): String = kotlinx.io.core.String(this.readUShortLVByteArray())
internal inline fun Input.readUShortLVByteArray(): ByteArray = this.readBytes(this.readUShort().toInt())

View File

@ -16,25 +16,27 @@ import io.ktor.http.HttpStatusCode
import io.ktor.http.URLProtocol
import io.ktor.http.content.OutgoingContent
import io.ktor.http.userAgent
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.copyAndClose
import io.ktor.utils.io.core.Input
import io.ktor.utils.io.core.readAvailable
import io.ktor.utils.io.core.readInt
import io.ktor.utils.io.core.use
import io.ktor.utils.io.pool.useInstance
import io.ktor.utils.io.ByteWriteChannel
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.io.ByteReadChannel
import kotlinx.io.InputStream
import kotlinx.io.core.Input
import kotlinx.io.core.discardExact
import kotlinx.io.core.readAvailable
import kotlinx.io.core.use
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.copyAndClose
import net.mamoe.mirai.utils.io.ByteArrayPool
import net.mamoe.mirai.utils.io.PlatformSocket
import net.mamoe.mirai.utils.io.withUse
import kotlinx.serialization.InternalSerializationApi
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class, InternalSerializationApi::class)
@Suppress("SpellCheckingInspection")
internal suspend fun HttpClient.postImage(
htcmd: String,
@ -67,7 +69,7 @@ internal suspend fun HttpClient.postImage(
override val contentType: ContentType = ContentType.Image.Any
override val contentLength: Long = inputSize
override suspend fun writeTo(channel: io.ktor.utils.io.ByteWriteChannel) {
override suspend fun writeTo(channel: ByteWriteChannel) {
ByteArrayPool.useInstance { buffer: ByteArray ->
when (imageInput) {
is Input -> {
@ -92,9 +94,9 @@ internal suspend fun HttpClient.postImage(
}
} == HttpStatusCode.OK
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class, InternalSerializationApi::class)
internal object HighwayHelper {
@UseExperimental(InternalCoroutinesApi::class)
@OptIn(InternalCoroutinesApi::class)
suspend fun uploadImage(
client: QQAndroidClient,
serverIp: String,

View File

@ -11,19 +11,24 @@
package net.mamoe.mirai.qqandroid.network.highway
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.io.ByteReadChannel
import kotlinx.io.InputStream
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Input
import kotlinx.io.core.buildPacket
import kotlinx.io.core.writeFully
import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.io.*
import kotlinx.serialization.InternalSerializationApi
import net.mamoe.mirai.utils.MiraiPlatformUtils
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class, InternalSerializationApi::class)
internal fun createImageDataPacketSequence( // RequestDataTrans
client: QQAndroidClient,
command: String,
@ -73,7 +78,7 @@ internal fun createImageDataPacketSequence( // RequestDataTrans
dataoffset = offset,
filesize = dataSize.toLong(),
serviceticket = uKey,
md5 = net.mamoe.mirai.utils.md5(chunkedInput.buffer, 0, chunkedInput.bufferSize),
md5 = MiraiPlatformUtils.md5(chunkedInput.buffer, 0, chunkedInput.bufferSize),
fileMd5 = fileMd5,
flag = 0,
rtcode = 0

View File

@ -9,139 +9,139 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
@Serializable
internal class BigDataChannel(
@SerialId(0) val vBigdataIplists: List<BigDataIpList>,
@SerialId(1) val sBigdataSigSession: ByteArray? = null,
@SerialId(2) val sBigdataKeySession: ByteArray? = null,
@SerialId(3) val uSigUin: Long? = null,
@SerialId(4) val iConnectFlag: Int? = 1,
@SerialId(5) val vBigdataPbBuf: ByteArray? = null
@JceId(0) val vBigdataIplists: List<BigDataIpList>,
@JceId(1) val sBigdataSigSession: ByteArray? = null,
@JceId(2) val sBigdataKeySession: ByteArray? = null,
@JceId(3) val uSigUin: Long? = null,
@JceId(4) val iConnectFlag: Int? = 1,
@JceId(5) val vBigdataPbBuf: ByteArray? = null
) : JceStruct
@Serializable
internal class BigDataIpInfo(
@SerialId(0) val uType: Long,
@SerialId(1) val sIp: String = "",
@SerialId(2) val uPort: Long
@JceId(0) val uType: Long,
@JceId(1) val sIp: String = "",
@JceId(2) val uPort: Long
) : JceStruct
@Serializable
internal class BigDataIpList(
@SerialId(0) val uServiceType: Long,
@SerialId(1) val vIplist: List<BigDataIpInfo>,
@SerialId(2) val netSegConfs: List<NetSegConf>? = null,
@SerialId(3) val ufragmentSize: Long? = null
@JceId(0) val uServiceType: Long,
@JceId(1) val vIplist: List<BigDataIpInfo>,
@JceId(2) val netSegConfs: List<NetSegConf>? = null,
@JceId(3) val ufragmentSize: Long? = null
) : JceStruct
@Serializable
internal class ClientLogConfig(
@SerialId(1) val type: Int,
@SerialId(2) val timeStart: TimeStamp? = null,
@SerialId(3) val timeFinish: TimeStamp? = null,
@SerialId(4) val loglevel: Byte? = null,
@SerialId(5) val cookie: Int? = null,
@SerialId(6) val lseq: Long? = null
@JceId(1) val type: Int,
@JceId(2) val timeStart: TimeStamp? = null,
@JceId(3) val timeFinish: TimeStamp? = null,
@JceId(4) val loglevel: Byte? = null,
@JceId(5) val cookie: Int? = null,
@JceId(6) val lseq: Long? = null
) : JceStruct
@Serializable
internal class DomainIpChannel(
@SerialId(0) val vDomainIplists: List<DomainIpList>
@JceId(0) val vDomainIplists: List<DomainIpList>
) : JceStruct
@Serializable
internal class DomainIpInfo(
@SerialId(1) val uIp: Int,
@SerialId(2) val uPort: Int
@JceId(1) val uIp: Int,
@JceId(2) val uPort: Int
) : JceStruct
@Serializable
internal class DomainIpList(
@SerialId(0) val uDomainType: Int,
@SerialId(1) val vIplist: List<DomainIpInfo>
@JceId(0) val uDomainType: Int,
@JceId(1) val vIplist: List<DomainIpInfo>
) : JceStruct
@Serializable
internal class FileStoragePushFSSvcList(
@SerialId(0) val vUpLoadList: List<FileStorageServerListInfo>,
@SerialId(1) val vPicDownLoadList: List<FileStorageServerListInfo>,
@SerialId(2) val vGPicDownLoadList: List<FileStorageServerListInfo>? = null,
@SerialId(3) val vQzoneProxyServiceList: List<FileStorageServerListInfo>? = null,
@SerialId(4) val vUrlEncodeServiceList: List<FileStorageServerListInfo>? = null,
@SerialId(5) val bigDataChannel: BigDataChannel? = null,
@SerialId(6) val vVipEmotionList: List<FileStorageServerListInfo>? = null,
@SerialId(7) val vC2CPicDownList: List<FileStorageServerListInfo>? = null,
@SerialId(8) val fmtIPInfo: FmtIPInfo? = null,
@SerialId(9) val domainIpChannel: DomainIpChannel? = null,
@SerialId(10) val pttlist: ByteArray? = null
@JceId(0) val vUpLoadList: List<FileStorageServerListInfo>,
@JceId(1) val vPicDownLoadList: List<FileStorageServerListInfo>,
@JceId(2) val vGPicDownLoadList: List<FileStorageServerListInfo>? = null,
@JceId(3) val vQzoneProxyServiceList: List<FileStorageServerListInfo>? = null,
@JceId(4) val vUrlEncodeServiceList: List<FileStorageServerListInfo>? = null,
@JceId(5) val bigDataChannel: BigDataChannel? = null,
@JceId(6) val vVipEmotionList: List<FileStorageServerListInfo>? = null,
@JceId(7) val vC2CPicDownList: List<FileStorageServerListInfo>? = null,
@JceId(8) val fmtIPInfo: FmtIPInfo? = null,
@JceId(9) val domainIpChannel: DomainIpChannel? = null,
@JceId(10) val pttlist: ByteArray? = null
) : JceStruct
@Serializable
internal class FileStorageServerListInfo(
@SerialId(1) val sIP: String = "",
@SerialId(2) val iPort: Int
@JceId(1) val sIP: String = "",
@JceId(2) val iPort: Int
) : JceStruct
@Serializable
internal class FmtIPInfo(
@SerialId(0) val sGateIp: String = "",
@SerialId(1) val iGateIpOper: Long
@JceId(0) val sGateIp: String = "",
@JceId(1) val iGateIpOper: Long
) : JceStruct
@Serializable
internal class NetSegConf(
@SerialId(0) val uint32NetType: Long? = null,
@SerialId(1) val uint32Segsize: Long? = null,
@SerialId(2) val uint32Segnum: Long? = null,
@SerialId(3) val uint32Curconnnum: Long? = null
@JceId(0) val uint32NetType: Long? = null,
@JceId(1) val uint32Segsize: Long? = null,
@JceId(2) val uint32Segnum: Long? = null,
@JceId(3) val uint32Curconnnum: Long? = null
) : JceStruct
@Suppress("ArrayInDataClass")
@Serializable
internal data class PushReq(
@SerialId(1) val type: Int,
@SerialId(2) val jcebuf: ByteArray,
@SerialId(3) val seq: Long
@JceId(1) val type: Int,
@JceId(2) val jcebuf: ByteArray,
@JceId(3) val seq: Long
) : JceStruct, Packet
@Serializable
internal class PushResp(
@SerialId(1) val type: Int,
@SerialId(2) val seq: Long,
@SerialId(3) val jcebuf: ByteArray? = null
@JceId(1) val type: Int,
@JceId(2) val seq: Long,
@JceId(3) val jcebuf: ByteArray? = null
) : JceStruct
@Serializable
internal class SsoServerList(
@SerialId(1) val v2G3GList: List<SsoServerListInfo>,
@SerialId(3) val vWifiList: List<SsoServerListInfo>,
@SerialId(4) val iReconnect: Int,
@SerialId(5) val testSpeed: Byte? = null,
@SerialId(6) val useNewList: Byte? = null,
@SerialId(7) val iMultiConn: Int? = 1,
@SerialId(8) val vHttp2g3glist: List<SsoServerListInfo>? = null,
@SerialId(9) val vHttpWifilist: List<SsoServerListInfo>? = null
@JceId(1) val v2G3GList: List<SsoServerListInfo>,
@JceId(3) val vWifiList: List<SsoServerListInfo>,
@JceId(4) val iReconnect: Int,
@JceId(5) val testSpeed: Byte? = null,
@JceId(6) val useNewList: Byte? = null,
@JceId(7) val iMultiConn: Int? = 1,
@JceId(8) val vHttp2g3glist: List<SsoServerListInfo>? = null,
@JceId(9) val vHttpWifilist: List<SsoServerListInfo>? = null
) : JceStruct
@Serializable
internal class SsoServerListInfo(
@SerialId(1) val sIP: String = "",
@SerialId(2) val iPort: Int,
@SerialId(3) val linkType: Byte,
@SerialId(4) val proxy: Byte,
@SerialId(5) val protocolType: Byte? = null,
@SerialId(6) val iTimeOut: Int? = 10
@JceId(1) val sIP: String = "",
@JceId(2) val iPort: Int,
@JceId(3) val linkType: Byte,
@JceId(4) val proxy: Byte,
@JceId(5) val protocolType: Byte? = null,
@JceId(6) val iTimeOut: Int? = 10
) : JceStruct
@Serializable
internal class TimeStamp(
@SerialId(1) val year: Int,
@SerialId(2) val month: Byte,
@SerialId(3) val day: Byte,
@SerialId(4) val hour: Byte
@JceId(1) val year: Int,
@JceId(2) val month: Byte,
@JceId(3) val day: Byte,
@JceId(4) val hour: Byte
) : JceStruct

View File

@ -9,172 +9,172 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
@Serializable
internal class ModifyGroupCardReq(
@SerialId(0) val dwZero: Long,
@SerialId(1) val dwGroupCode: Long,
@SerialId(2) val dwNewSeq: Long,
@SerialId(3) val vecUinInfo: List<stUinInfo>
@JceId(0) val dwZero: Long,
@JceId(1) val dwGroupCode: Long,
@JceId(2) val dwNewSeq: Long,
@JceId(3) val vecUinInfo: List<stUinInfo>
) : JceStruct
@Serializable
internal class stUinInfo(
@SerialId(0) val dwuin: Long,
@SerialId(1) val dwFlag: Long,
@SerialId(2) val sName: String = "",
@SerialId(3) val gender: Byte,
@SerialId(4) val sPhone: String = "",
@SerialId(5) val sEmail: String = "",
@SerialId(6) val sRemark: String = ""
@JceId(0) val dwuin: Long,
@JceId(1) val dwFlag: Long,
@JceId(2) val sName: String = "",
@JceId(3) val gender: Byte,
@JceId(4) val sPhone: String = "",
@JceId(5) val sEmail: String = "",
@JceId(6) val sRemark: String = ""
) : JceStruct
@Serializable
internal class GetFriendListReq(
@SerialId(0) val reqtype: Int? = null,
@SerialId(1) val ifReflush: Byte? = null,
@SerialId(2) val uin: Long? = null,
@SerialId(3) val startIndex: Short? = null,
@SerialId(4) val getfriendCount: Short? = null,
@SerialId(5) val groupid: Byte? = null,
@SerialId(6) val ifGetGroupInfo: Byte? = null,
@SerialId(7) val groupstartIndex: Byte? = null,
@SerialId(8) val getgroupCount: Byte? = null,
@SerialId(9) val ifGetMSFGroup: Byte? = null,
@SerialId(10) val ifShowTermType: Byte? = null,
@SerialId(11) val version: Long? = null,
@SerialId(12) val uinList: List<Long>? = null,
@SerialId(13) val eAppType: Int = 0,
@SerialId(14) val ifGetDOVId: Byte? = null,
@SerialId(15) val ifGetBothFlag: Byte? = null,
@SerialId(16) val vec0xd50Req: ByteArray? = null,
@SerialId(17) val vec0xd6bReq: ByteArray? = null,
@SerialId(18) val vecSnsTypelist: List<Long>? = null
@JceId(0) val reqtype: Int? = null,
@JceId(1) val ifReflush: Byte? = null,
@JceId(2) val uin: Long? = null,
@JceId(3) val startIndex: Short? = null,
@JceId(4) val getfriendCount: Short? = null,
@JceId(5) val groupid: Byte? = null,
@JceId(6) val ifGetGroupInfo: Byte? = null,
@JceId(7) val groupstartIndex: Byte? = null,
@JceId(8) val getgroupCount: Byte? = null,
@JceId(9) val ifGetMSFGroup: Byte? = null,
@JceId(10) val ifShowTermType: Byte? = null,
@JceId(11) val version: Long? = null,
@JceId(12) val uinList: List<Long>? = null,
@JceId(13) val eAppType: Int = 0,
@JceId(14) val ifGetDOVId: Byte? = null,
@JceId(15) val ifGetBothFlag: Byte? = null,
@JceId(16) val vec0xd50Req: ByteArray? = null,
@JceId(17) val vec0xd6bReq: ByteArray? = null,
@JceId(18) val vecSnsTypelist: List<Long>? = null
) : JceStruct
@Serializable
internal class GetFriendListResp(
@SerialId(0) val reqtype: Int,
@SerialId(1) val ifReflush: Byte,
@SerialId(2) val uin: Long,
@SerialId(3) val startIndex: Short,
@SerialId(4) val getfriendCount: Short,
@SerialId(5) val totoalFriendCount: Short,
@SerialId(6) val friendCount: Short,
@SerialId(7) val vecFriendInfo: List<FriendInfo>? = null,
@SerialId(8) val groupid: Byte? = null,
@SerialId(9) val ifGetGroupInfo: Byte,
@SerialId(10) val groupstartIndex: Byte? = null,
@SerialId(11) val getgroupCount: Byte? = null,
@SerialId(12) val totoalGroupCount: Short? = null,
@SerialId(13) val groupCount: Byte? = null,
@SerialId(14) val vecGroupInfo: List<GroupInfo>? = null,
@SerialId(15) val result: Int,
@SerialId(16) val errorCode: Short? = null,
@SerialId(17) val onlineFriendCount: Short? = null,
@SerialId(18) val serverTime: Long? = null,
@SerialId(19) val sqqOnLineCount: Short? = null,
@SerialId(20) val vecMSFGroupInfo: List<GroupInfo>? = null,
@SerialId(21) val respType: Byte? = null,
@SerialId(22) val hasOtherRespFlag: Byte? = null,
@SerialId(23) val stSelfInfo: FriendInfo? = null,
@SerialId(24) val showPcIcon: Byte? = null,
@SerialId(25) val wGetExtSnsRspCode: Short? = null,
@SerialId(26) val stSubSrvRspCode: FriendListSubSrvRspCode? = null
@JceId(0) val reqtype: Int,
@JceId(1) val ifReflush: Byte,
@JceId(2) val uin: Long,
@JceId(3) val startIndex: Short,
@JceId(4) val getfriendCount: Short,
@JceId(5) val totoalFriendCount: Short,
@JceId(6) val friendCount: Short,
@JceId(7) val vecFriendInfo: List<FriendInfo>? = null,
@JceId(8) val groupid: Byte? = null,
@JceId(9) val ifGetGroupInfo: Byte,
@JceId(10) val groupstartIndex: Byte? = null,
@JceId(11) val getgroupCount: Byte? = null,
@JceId(12) val totoalGroupCount: Short? = null,
@JceId(13) val groupCount: Byte? = null,
@JceId(14) val vecGroupInfo: List<GroupInfo>? = null,
@JceId(15) val result: Int,
@JceId(16) val errorCode: Short? = null,
@JceId(17) val onlineFriendCount: Short? = null,
@JceId(18) val serverTime: Long? = null,
@JceId(19) val sqqOnLineCount: Short? = null,
@JceId(20) val vecMSFGroupInfo: List<GroupInfo>? = null,
@JceId(21) val respType: Byte? = null,
@JceId(22) val hasOtherRespFlag: Byte? = null,
@JceId(23) val stSelfInfo: FriendInfo? = null,
@JceId(24) val showPcIcon: Byte? = null,
@JceId(25) val wGetExtSnsRspCode: Short? = null,
@JceId(26) val stSubSrvRspCode: FriendListSubSrvRspCode? = null
) : JceStruct
@Serializable
internal class FriendListSubSrvRspCode(
@SerialId(0) val wGetMutualMarkRspCode: Short? = null,
@SerialId(1) val wGetIntimateInfoRspCode: Short? = null
@JceId(0) val wGetMutualMarkRspCode: Short? = null,
@JceId(1) val wGetIntimateInfoRspCode: Short? = null
) : JceStruct
@Serializable
internal class FriendInfo(
@SerialId(0) val friendUin: Long,
@SerialId(1) val groupId: Byte,
@SerialId(2) val faceId: Short,
@SerialId(3) val remark: String = "",
@SerialId(4) val sqqtype: Byte,
@SerialId(5) val status: Byte = 20,
@SerialId(6) val memberLevel: Byte? = null,
@SerialId(7) val isMqqOnLine: Byte? = null,
@SerialId(8) val sqqOnLineState: Byte? = null,
@SerialId(9) val isIphoneOnline: Byte? = null,
@SerialId(10) val detalStatusFlag: Byte? = null,
@SerialId(11) val sqqOnLineStateV2: Byte? = null,
@SerialId(12) val sShowName: String? = "",
@SerialId(13) val isRemark: Byte? = null,
@SerialId(14) val nick: String? = "",
@SerialId(15) val specialFlag: Byte? = null,
@SerialId(16) val vecIMGroupID: ByteArray? = null,
@SerialId(17) val vecMSFGroupID: ByteArray? = null,
@SerialId(18) val iTermType: Int? = null,
@SerialId(19) val oVipInfo: VipBaseInfo? = null,
@SerialId(20) val network: Byte? = null,
@SerialId(21) val vecRing: ByteArray? = null,
@SerialId(22) val uAbiFlag: Long? = null,
@SerialId(23) val ulFaceAddonId: Long? = null,
@SerialId(24) val eNetworkType: Int? = 0,
@SerialId(25) val uVipFont: Long? = null,
@SerialId(26) val eIconType: Int? = 0,
@SerialId(27) val termDesc: String? = "",
@SerialId(28) val uColorRing: Long? = null,
@SerialId(29) val apolloFlag: Byte? = null,
@SerialId(30) val uApolloTimestamp: Long? = null,
@SerialId(31) val sex: Byte? = null,
@SerialId(32) val uFounderFont: Long? = null,
@SerialId(33) val eimId: String? = "",
@SerialId(34) val eimMobile: String? = "",
@SerialId(35) val olympicTorch: Byte? = null,
@SerialId(36) val uApolloSignTime: Long? = null,
@SerialId(37) val uLaviUin: Long? = null,
@SerialId(38) val uTagUpdateTime: Long? = null,
@SerialId(39) val uGameLastLoginTime: Long? = null,
@SerialId(40) val uGameAppid: Long? = null,
@SerialId(41) val vecCardID: ByteArray? = null,
@SerialId(42) val ulBitSet: Long? = null,
@SerialId(43) val kingOfGloryFlag: Byte? = null,
@SerialId(44) val ulKingOfGloryRank: Long? = null,
@SerialId(45) val masterUin: String? = "",
@SerialId(46) val uLastMedalUpdateTime: Long? = null,
@SerialId(47) val uFaceStoreId: Long? = null,
@SerialId(48) val uFontEffect: Long? = null,
@SerialId(49) val sDOVId: String? = "",
@SerialId(50) val uBothFlag: Long? = null,
@SerialId(51) val centiShow3DFlag: Byte? = null,
@SerialId(52) val vecIntimateInfo: ByteArray? = null,
@SerialId(53) val showNameplate: Byte? = null,
@SerialId(54) val newLoverDiamondFlag: Byte? = null,
@SerialId(55) val vecExtSnsFrdData: ByteArray? = null,
@SerialId(56) val vecMutualMarkData: ByteArray? = null
@JceId(0) val friendUin: Long,
@JceId(1) val groupId: Byte,
@JceId(2) val faceId: Short,
@JceId(3) val remark: String = "",
@JceId(4) val sqqtype: Byte,
@JceId(5) val status: Byte = 20,
@JceId(6) val memberLevel: Byte? = null,
@JceId(7) val isMqqOnLine: Byte? = null,
@JceId(8) val sqqOnLineState: Byte? = null,
@JceId(9) val isIphoneOnline: Byte? = null,
@JceId(10) val detalStatusFlag: Byte? = null,
@JceId(11) val sqqOnLineStateV2: Byte? = null,
@JceId(12) val sShowName: String? = "",
@JceId(13) val isRemark: Byte? = null,
@JceId(14) val nick: String? = "",
@JceId(15) val specialFlag: Byte? = null,
@JceId(16) val vecIMGroupID: ByteArray? = null,
@JceId(17) val vecMSFGroupID: ByteArray? = null,
@JceId(18) val iTermType: Int? = null,
@JceId(19) val oVipInfo: VipBaseInfo? = null,
@JceId(20) val network: Byte? = null,
@JceId(21) val vecRing: ByteArray? = null,
@JceId(22) val uAbiFlag: Long? = null,
@JceId(23) val ulFaceAddonId: Long? = null,
@JceId(24) val eNetworkType: Int? = 0,
@JceId(25) val uVipFont: Long? = null,
@JceId(26) val eIconType: Int? = 0,
@JceId(27) val termDesc: String? = "",
@JceId(28) val uColorRing: Long? = null,
@JceId(29) val apolloFlag: Byte? = null,
@JceId(30) val uApolloTimestamp: Long? = null,
@JceId(31) val sex: Byte? = null,
@JceId(32) val uFounderFont: Long? = null,
@JceId(33) val eimId: String? = "",
@JceId(34) val eimMobile: String? = "",
@JceId(35) val olympicTorch: Byte? = null,
@JceId(36) val uApolloSignTime: Long? = null,
@JceId(37) val uLaviUin: Long? = null,
@JceId(38) val uTagUpdateTime: Long? = null,
@JceId(39) val uGameLastLoginTime: Long? = null,
@JceId(40) val uGameAppid: Long? = null,
@JceId(41) val vecCardID: ByteArray? = null,
@JceId(42) val ulBitSet: Long? = null,
@JceId(43) val kingOfGloryFlag: Byte? = null,
@JceId(44) val ulKingOfGloryRank: Long? = null,
@JceId(45) val masterUin: String? = "",
@JceId(46) val uLastMedalUpdateTime: Long? = null,
@JceId(47) val uFaceStoreId: Long? = null,
@JceId(48) val uFontEffect: Long? = null,
@JceId(49) val sDOVId: String? = "",
@JceId(50) val uBothFlag: Long? = null,
@JceId(51) val centiShow3DFlag: Byte? = null,
@JceId(52) val vecIntimateInfo: ByteArray? = null,
@JceId(53) val showNameplate: Byte? = null,
@JceId(54) val newLoverDiamondFlag: Byte? = null,
@JceId(55) val vecExtSnsFrdData: ByteArray? = null,
@JceId(56) val vecMutualMarkData: ByteArray? = null
) : JceStruct
@Serializable
internal class VipBaseInfo(
@SerialId(0) val mOpenInfo: Map<Int, VipOpenInfo>
@JceId(0) val mOpenInfo: Map<Int, VipOpenInfo>
) : JceStruct
@Serializable
internal class VipOpenInfo(
@SerialId(0) val open: Boolean,
@SerialId(1) val iVipType: Int = -1,
@SerialId(2) val iVipLevel: Int = -1,
@SerialId(3) val iVipFlag: Int? = null,
@SerialId(4) val nameplateId: Long? = null
@JceId(0) val open: Boolean,
@JceId(1) val iVipType: Int = -1,
@JceId(2) val iVipLevel: Int = -1,
@JceId(3) val iVipFlag: Int? = null,
@JceId(4) val nameplateId: Long? = null
) : JceStruct
@Serializable
internal class GroupInfo(
@SerialId(0) val groupId: Byte,
@SerialId(1) val groupname: String = "",
@SerialId(2) val friendCount: Int,
@SerialId(3) val onlineFriendCount: Int,
@SerialId(4) val seqid: Byte? = null,
@SerialId(5) val sqqOnLineCount: Int? = null
@JceId(0) val groupId: Byte,
@JceId(1) val groupname: String = "",
@JceId(2) val friendCount: Int,
@JceId(3) val onlineFriendCount: Int,
@JceId(4) val seqid: Byte? = null,
@JceId(5) val sqqOnLineCount: Int? = null
) : JceStruct

View File

@ -9,250 +9,250 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
internal class OnlinePushPack {
@Serializable
internal class DelMsgInfo(
@SerialId(0) val fromUin: Long,
@SerialId(1) val uMsgTime: Long,
@SerialId(2) val shMsgSeq: Short,
@SerialId(3) val vMsgCookies: ByteArray? = null,
@SerialId(4) val wCmd: Short? = null,
@SerialId(5) val uMsgType: Long? = null,
@SerialId(6) val uAppId: Long? = null,
@SerialId(7) val sendTime: Long? = null,
@SerialId(8) val ssoSeq: Int? = null,
@SerialId(9) val ssoIp: Int? = null,
@SerialId(10) val clientIp: Int? = null
@JceId(0) val fromUin: Long,
@JceId(1) val uMsgTime: Long,
@JceId(2) val shMsgSeq: Short,
@JceId(3) val vMsgCookies: ByteArray? = null,
@JceId(4) val wCmd: Short? = null,
@JceId(5) val uMsgType: Long? = null,
@JceId(6) val uAppId: Long? = null,
@JceId(7) val sendTime: Long? = null,
@JceId(8) val ssoSeq: Int? = null,
@JceId(9) val ssoIp: Int? = null,
@JceId(10) val clientIp: Int? = null
) : JceStruct
@Serializable
internal class DeviceInfo(
@SerialId(0) val netType: Byte? = null,
@SerialId(1) val devType: String? = "",
@SerialId(2) val oSVer: String? = "",
@SerialId(3) val vendorName: String? = "",
@SerialId(4) val vendorOSName: String? = "",
@SerialId(5) val iOSIdfa: String? = ""
@JceId(0) val netType: Byte? = null,
@JceId(1) val devType: String? = "",
@JceId(2) val oSVer: String? = "",
@JceId(3) val vendorName: String? = "",
@JceId(4) val vendorOSName: String? = "",
@JceId(5) val iOSIdfa: String? = ""
) : JceStruct
@Serializable
internal class Name(
@SerialId(0) val fromUin: Long,
@SerialId(1) val uMsgTime: Long,
@SerialId(2) val shMsgType: Short,
@SerialId(3) val shMsgSeq: Short,
@SerialId(4) val msg: String = "",
@SerialId(5) val uRealMsgTime: Int? = null,
@SerialId(6) val vMsg: ByteArray? = null,
@SerialId(7) val uAppShareID: Long? = null,
@SerialId(8) val vMsgCookies: ByteArray? = null,
@SerialId(9) val vAppShareCookie: ByteArray? = null,
@SerialId(10) val msgUid: Long? = null,
@SerialId(11) val lastChangeTime: Long? = 1L,
@SerialId(12) val vCPicInfo: List<CPicInfo>? = null,
@SerialId(13) val stShareData: ShareData? = null,
@SerialId(14) val fromInstId: Long? = null,
@SerialId(15) val vRemarkOfSender: ByteArray? = null,
@SerialId(16) val fromMobile: String? = "",
@SerialId(17) val fromName: String? = "",
@SerialId(18) val vNickName: List<String>? = null,
@SerialId(19) val stC2CTmpMsgHead: TempMsgHead? = null
@JceId(0) val fromUin: Long,
@JceId(1) val uMsgTime: Long,
@JceId(2) val shMsgType: Short,
@JceId(3) val shMsgSeq: Short,
@JceId(4) val msg: String = "",
@JceId(5) val uRealMsgTime: Int? = null,
@JceId(6) val vMsg: ByteArray? = null,
@JceId(7) val uAppShareID: Long? = null,
@JceId(8) val vMsgCookies: ByteArray? = null,
@JceId(9) val vAppShareCookie: ByteArray? = null,
@JceId(10) val msgUid: Long? = null,
@JceId(11) val lastChangeTime: Long? = 1L,
@JceId(12) val vCPicInfo: List<CPicInfo>? = null,
@JceId(13) val stShareData: ShareData? = null,
@JceId(14) val fromInstId: Long? = null,
@JceId(15) val vRemarkOfSender: ByteArray? = null,
@JceId(16) val fromMobile: String? = "",
@JceId(17) val fromName: String? = "",
@JceId(18) val vNickName: List<String>? = null,
@JceId(19) val stC2CTmpMsgHead: TempMsgHead? = null
) : JceStruct
@Serializable
internal class SvcReqPushMsg(
@SerialId(0) val uin: Long,
@SerialId(1) val uMsgTime: Long,
@SerialId(2) val vMsgInfos: List<MsgInfo>,
@SerialId(3) val svrip: Int? = 0,
@SerialId(4) val vSyncCookie: ByteArray? = null,
@SerialId(5) val vUinPairMsg: List<UinPairMsg>? = null,
@SerialId(6) val mPreviews: Map<String, ByteArray>? = null
@JceId(0) val uin: Long,
@JceId(1) val uMsgTime: Long,
@JceId(2) val vMsgInfos: List<MsgInfo>,
@JceId(3) val svrip: Int? = 0,
@JceId(4) val vSyncCookie: ByteArray? = null,
@JceId(5) val vUinPairMsg: List<UinPairMsg>? = null,
@JceId(6) val mPreviews: Map<String, ByteArray>? = null
// @SerialId(7) val wUserActive: Int? = null,
//@SerialId(12) val wGeneralFlag: Int? = null
) : JceStruct
@Serializable
internal class SvcRespPushMsg(
@SerialId(0) val uin: Long,
@SerialId(1) val vDelInfos: List<DelMsgInfo>,
@SerialId(2) val svrip: Int,
@SerialId(3) val pushToken: ByteArray? = null,
@SerialId(4) val serviceType: Int? = null,
@SerialId(5) val deviceInfo: DeviceInfo? = null
@JceId(0) val uin: Long,
@JceId(1) val vDelInfos: List<DelMsgInfo>,
@JceId(2) val svrip: Int,
@JceId(3) val pushToken: ByteArray? = null,
@JceId(4) val serviceType: Int? = null,
@JceId(5) val deviceInfo: DeviceInfo? = null
) : JceStruct
@Serializable
internal class UinPairMsg(
@SerialId(1) val uLastReadTime: Long? = null,
@SerialId(2) val peerUin: Long? = null,
@SerialId(3) val uMsgCompleted: Long? = null,
@SerialId(4) val vMsgInfos: List<MsgInfo>? = null
@JceId(1) val uLastReadTime: Long? = null,
@JceId(2) val peerUin: Long? = null,
@JceId(3) val uMsgCompleted: Long? = null,
@JceId(4) val vMsgInfos: List<MsgInfo>? = null
) : JceStruct
@Serializable
internal class MsgType0x210(
@SerialId(0) val uSubMsgType: Long,
@SerialId(1) val stMsgInfo0x2: MsgType0x210SubMsgType0x2? = null,
@SerialId(3) val stMsgInfo0xa: MsgType0x210SubMsgType0xa? = null,
@SerialId(4) val stMsgInfo0xe: MsgType0x210SubMsgType0xe? = null,
@SerialId(5) val stMsgInfo0x13: MsgType0x210SubMsgType0x13? = null,
@SerialId(6) val stMsgInfo0x17: MsgType0x210SubMsgType0x17? = null,
@SerialId(7) val stMsgInfo0x20: MsgType0x210SubMsgType0x20? = null,
@SerialId(8) val stMsgInfo0x1d: MsgType0x210SubMsgType0x1d? = null,
@SerialId(9) val stMsgInfo0x24: MsgType0x210SubMsgType0x24? = null,
@SerialId(10) val vProtobuf: ByteArray? = null
@JceId(0) val uSubMsgType: Long,
@JceId(1) val stMsgInfo0x2: MsgType0x210SubMsgType0x2? = null,
@JceId(3) val stMsgInfo0xa: MsgType0x210SubMsgType0xa? = null,
@JceId(4) val stMsgInfo0xe: MsgType0x210SubMsgType0xe? = null,
@JceId(5) val stMsgInfo0x13: MsgType0x210SubMsgType0x13? = null,
@JceId(6) val stMsgInfo0x17: MsgType0x210SubMsgType0x17? = null,
@JceId(7) val stMsgInfo0x20: MsgType0x210SubMsgType0x20? = null,
@JceId(8) val stMsgInfo0x1d: MsgType0x210SubMsgType0x1d? = null,
@JceId(9) val stMsgInfo0x24: MsgType0x210SubMsgType0x24? = null,
@JceId(10) val vProtobuf: ByteArray? = null
) : JceStruct
@Serializable
internal class MsgType0x210SubMsgType0x13(
@SerialId(0) val uint32SrcAppId: Long? = null,
@SerialId(1) val uint32SrcInstId: Long? = null,
@SerialId(2) val uint32DstAppId: Long? = null,
@SerialId(3) val uint32DstInstId: Long? = null,
@SerialId(4) val uint64DstUin: Long? = null,
@SerialId(5) val uint64Sessionid: Long? = null,
@SerialId(6) val uint32Size: Long? = null,
@SerialId(7) val uint32Index: Long? = null,
@SerialId(8) val uint32Type: Long? = null,
@SerialId(9) val buf: ByteArray? = null
@JceId(0) val uint32SrcAppId: Long? = null,
@JceId(1) val uint32SrcInstId: Long? = null,
@JceId(2) val uint32DstAppId: Long? = null,
@JceId(3) val uint32DstInstId: Long? = null,
@JceId(4) val uint64DstUin: Long? = null,
@JceId(5) val uint64Sessionid: Long? = null,
@JceId(6) val uint32Size: Long? = null,
@JceId(7) val uint32Index: Long? = null,
@JceId(8) val uint32Type: Long? = null,
@JceId(9) val buf: ByteArray? = null
) : JceStruct
@Serializable
internal class MsgType0x210SubMsgType0x17(
@SerialId(0) val dwOpType: Long? = null,
@SerialId(1) val stAddGroup: AddGroup? = null,
@SerialId(2) val stDelGroup: DelGroup? = null,
@SerialId(3) val stModGroupName: ModGroupName? = null,
@SerialId(4) val stModGroupSort: ModGroupSort? = null,
@SerialId(5) val stModFriendGroup: ModFriendGroup? = null
@JceId(0) val dwOpType: Long? = null,
@JceId(1) val stAddGroup: AddGroup? = null,
@JceId(2) val stDelGroup: DelGroup? = null,
@JceId(3) val stModGroupName: ModGroupName? = null,
@JceId(4) val stModGroupSort: ModGroupSort? = null,
@JceId(5) val stModFriendGroup: ModFriendGroup? = null
) : JceStruct
@Serializable
internal class AddGroup(
@SerialId(0) val dwGroupID: Long? = null,
@SerialId(1) val dwSortID: Long? = null,
@SerialId(2) val groupName: String? = ""
@JceId(0) val dwGroupID: Long? = null,
@JceId(1) val dwSortID: Long? = null,
@JceId(2) val groupName: String? = ""
) : JceStruct
@Serializable
internal class DelGroup(
@SerialId(0) val dwGroupID: Long? = null
@JceId(0) val dwGroupID: Long? = null
) : JceStruct
@Serializable
internal class ModFriendGroup(
@SerialId(0) val vMsgFrdGroup: List<FriendGroup>? = null
@JceId(0) val vMsgFrdGroup: List<FriendGroup>? = null
) : JceStruct
@Serializable
internal class FriendGroup(
@SerialId(0) val dwFuin: Long? = null,
@SerialId(1) val vOldGroupID: List<Long>? = null,
@SerialId(2) val vNewGroupID: List<Long>? = null
@JceId(0) val dwFuin: Long? = null,
@JceId(1) val vOldGroupID: List<Long>? = null,
@JceId(2) val vNewGroupID: List<Long>? = null
) : JceStruct
@Serializable
internal class ModGroupName(
@SerialId(0) val dwGroupID: Long? = null,
@SerialId(1) val groupName: String? = ""
@JceId(0) val dwGroupID: Long? = null,
@JceId(1) val groupName: String? = ""
) : JceStruct
@Serializable
internal class ModGroupSort(
@SerialId(0) val vMsgGroupSort: List<GroupSort>? = null
@JceId(0) val vMsgGroupSort: List<GroupSort>? = null
) : JceStruct
@Serializable
internal class GroupSort(
@SerialId(0) val dwGroupID: Long? = null,
@SerialId(1) val dwSortID: Long? = null
@JceId(0) val dwGroupID: Long? = null,
@JceId(1) val dwSortID: Long? = null
) : JceStruct
@Serializable
internal class MsgType0x210SubMsgType0x1d(
@SerialId(0) val dwOpType: Long? = null,
@SerialId(1) val dwUin: Long? = null,
@SerialId(2) val dwID: Long? = null,
@SerialId(3) val value: String? = ""
@JceId(0) val dwOpType: Long? = null,
@JceId(1) val dwUin: Long? = null,
@JceId(2) val dwID: Long? = null,
@JceId(3) val value: String? = ""
) : JceStruct
@Serializable
internal class MsgType0x210SubMsgType0x2(
@SerialId(0) val uSrcAppId: Long? = null,
@SerialId(1) val uSrcInstId: Long? = null,
@SerialId(2) val uDstAppId: Long? = null,
@SerialId(3) val uDstInstId: Long? = null,
@SerialId(4) val uDstUin: Long? = null,
@SerialId(5) val fileName: ByteArray? = null,
@SerialId(6) val fileIndex: ByteArray? = null,
@SerialId(7) val fileMd5: ByteArray? = null,
@SerialId(8) val fileKey: ByteArray? = null,
@SerialId(9) val uServerIp: Long? = null,
@SerialId(10) val uServerPort: Long? = null,
@SerialId(11) val fileLen: Long? = null,
@SerialId(12) val sessionId: Long? = null,
@SerialId(13) val originfileMd5: ByteArray? = null,
@SerialId(14) val uOriginfiletype: Long? = null,
@SerialId(15) val uSeq: Long? = null
@JceId(0) val uSrcAppId: Long? = null,
@JceId(1) val uSrcInstId: Long? = null,
@JceId(2) val uDstAppId: Long? = null,
@JceId(3) val uDstInstId: Long? = null,
@JceId(4) val uDstUin: Long? = null,
@JceId(5) val fileName: ByteArray? = null,
@JceId(6) val fileIndex: ByteArray? = null,
@JceId(7) val fileMd5: ByteArray? = null,
@JceId(8) val fileKey: ByteArray? = null,
@JceId(9) val uServerIp: Long? = null,
@JceId(10) val uServerPort: Long? = null,
@JceId(11) val fileLen: Long? = null,
@JceId(12) val sessionId: Long? = null,
@JceId(13) val originfileMd5: ByteArray? = null,
@JceId(14) val uOriginfiletype: Long? = null,
@JceId(15) val uSeq: Long? = null
) : JceStruct
@Serializable
internal class MsgType0x210SubMsgType0x20(
@SerialId(0) val dwOpType: Long? = null,
@SerialId(1) val dwType: Long? = null,
@SerialId(2) val dwUin: Long? = null,
@SerialId(3) val remaek: String? = ""
@JceId(0) val dwOpType: Long? = null,
@JceId(1) val dwType: Long? = null,
@JceId(2) val dwUin: Long? = null,
@JceId(3) val remaek: String? = ""
) : JceStruct
@Serializable
internal class MsgType0x210SubMsgType0x24(
@SerialId(0) val vPluginNumList: List<PluginNum>? = null
@JceId(0) val vPluginNumList: List<PluginNum>? = null
) : JceStruct
@Serializable
internal class PluginNum(
@SerialId(0) val dwID: Long? = null,
@SerialId(1) val dwNUm: Long? = null,
@SerialId(2) val flag: Byte? = null
@JceId(0) val dwID: Long? = null,
@JceId(1) val dwNUm: Long? = null,
@JceId(2) val flag: Byte? = null
) : JceStruct
@Serializable
internal class MsgType0x210SubMsgType0xa(
@SerialId(0) val uSrcAppId: Long? = null,
@SerialId(1) val uSrcInstId: Long? = null,
@SerialId(2) val uDstAppId: Long? = null,
@SerialId(3) val uDstInstId: Long? = null,
@SerialId(4) val uDstUin: Long? = null,
@SerialId(5) val uType: Long? = null,
@SerialId(6) val uServerIp: Long? = null,
@SerialId(7) val uServerPort: Long? = null,
@SerialId(8) val vUrlNotify: ByteArray? = null,
@SerialId(9) val vTokenKey: ByteArray? = null,
@SerialId(10) val uFileLen: Long? = null,
@SerialId(11) val fileName: ByteArray? = null,
@SerialId(12) val vMd5: ByteArray? = null,
@SerialId(13) val sessionId: Long? = null,
@SerialId(14) val originfileMd5: ByteArray? = null,
@SerialId(15) val uOriginfiletype: Long? = null,
@SerialId(16) val uSeq: Long? = null
@JceId(0) val uSrcAppId: Long? = null,
@JceId(1) val uSrcInstId: Long? = null,
@JceId(2) val uDstAppId: Long? = null,
@JceId(3) val uDstInstId: Long? = null,
@JceId(4) val uDstUin: Long? = null,
@JceId(5) val uType: Long? = null,
@JceId(6) val uServerIp: Long? = null,
@JceId(7) val uServerPort: Long? = null,
@JceId(8) val vUrlNotify: ByteArray? = null,
@JceId(9) val vTokenKey: ByteArray? = null,
@JceId(10) val uFileLen: Long? = null,
@JceId(11) val fileName: ByteArray? = null,
@JceId(12) val vMd5: ByteArray? = null,
@JceId(13) val sessionId: Long? = null,
@JceId(14) val originfileMd5: ByteArray? = null,
@JceId(15) val uOriginfiletype: Long? = null,
@JceId(16) val uSeq: Long? = null
) : JceStruct
@Serializable
internal class MsgType0x210SubMsgType0xe(
@SerialId(0) val uint32SrcAppId: Long? = null,
@SerialId(1) val uint32SrcInstId: Long? = null,
@SerialId(2) val uint32DstAppId: Long? = null,
@SerialId(3) val uint32DstInstId: Long? = null,
@SerialId(4) val uint64DstUin: Long? = null,
@SerialId(5) val uint64Sessionid: Long? = null,
@SerialId(6) val uint32Operate: Long? = null,
@SerialId(7) val uint32Seq: Long? = null,
@SerialId(8) val uint32Code: Long? = null,
@SerialId(9) val msg: String? = ""
@JceId(0) val uint32SrcAppId: Long? = null,
@JceId(1) val uint32SrcInstId: Long? = null,
@JceId(2) val uint32DstAppId: Long? = null,
@JceId(3) val uint32DstInstId: Long? = null,
@JceId(4) val uint64DstUin: Long? = null,
@JceId(5) val uint64Sessionid: Long? = null,
@JceId(6) val uint32Operate: Long? = null,
@JceId(7) val uint32Seq: Long? = null,
@JceId(8) val uint32Code: Long? = null,
@JceId(9) val msg: String? = ""
) : JceStruct
}

View File

@ -9,72 +9,72 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@Suppress("ArrayInDataClass")
@Serializable
internal data class RequestPushNotify(
@SerialId(0) val uin: Long? = 0L,
@SerialId(1) val ctype: Byte = 0,
@SerialId(2) val strService: String?,
@SerialId(3) val strCmd: String?,
@SerialId(4) val vNotifyCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@SerialId(5) val usMsgType: Int?,
@SerialId(6) val wUserActive: Int?,
@SerialId(7) val wGeneralFlag: Int?,
@SerialId(8) val bindedUin: Long?,
@SerialId(9) val stMsgInfo: MsgInfo?,
@SerialId(10) val msgCtrlBuf: String?,
@SerialId(11) val serverBuf: ByteArray?,
@SerialId(12) val pingFlag: Long?,
@SerialId(13) val svrip: Int?
@JceId(0) val uin: Long? = 0L,
@JceId(1) val ctype: Byte = 0,
@JceId(2) val strService: String?,
@JceId(3) val strCmd: String?,
@JceId(4) val vNotifyCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@JceId(5) val usMsgType: Int?,
@JceId(6) val wUserActive: Int?,
@JceId(7) val wGeneralFlag: Int?,
@JceId(8) val bindedUin: Long?,
@JceId(9) val stMsgInfo: MsgInfo?,
@JceId(10) val msgCtrlBuf: String?,
@JceId(11) val serverBuf: ByteArray?,
@JceId(12) val pingFlag: Long?,
@JceId(13) val svrip: Int?
) : JceStruct, Packet
@Serializable
internal class MsgInfo(
@SerialId(0) val lFromUin: Long? = 0L,
@SerialId(1) val uMsgTime: Long? = 0L,
@SerialId(2) val shMsgType: Short,
@SerialId(3) val shMsgSeq: Short,
@SerialId(4) val strMsg: String?,
@SerialId(5) val uRealMsgTime: Int?,
@SerialId(6) val vMsg: ByteArray?,
@SerialId(7) val uAppShareID: Long?,
@SerialId(8) val vMsgCookies: ByteArray? = EMPTY_BYTE_ARRAY,
@SerialId(9) val vAppShareCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@SerialId(10) val lMsgUid: Long?,
@SerialId(11) val lLastChangeTime: Long?,
@SerialId(12) val vCPicInfo: List<CPicInfo>?,
@SerialId(13) val stShareData: ShareData?,
@SerialId(14) val lFromInstId: Long?,
@SerialId(15) val vRemarkOfSender: ByteArray?,
@SerialId(16) val strFromMobile: String?,
@SerialId(17) val strFromName: String?,
@SerialId(18) val vNickName: List<String>?//,
@JceId(0) val lFromUin: Long? = 0L,
@JceId(1) val uMsgTime: Long? = 0L,
@JceId(2) val shMsgType: Short,
@JceId(3) val shMsgSeq: Short,
@JceId(4) val strMsg: String?,
@JceId(5) val uRealMsgTime: Int?,
@JceId(6) val vMsg: ByteArray?,
@JceId(7) val uAppShareID: Long?,
@JceId(8) val vMsgCookies: ByteArray? = EMPTY_BYTE_ARRAY,
@JceId(9) val vAppShareCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@JceId(10) val lMsgUid: Long?,
@JceId(11) val lLastChangeTime: Long?,
@JceId(12) val vCPicInfo: List<CPicInfo>?,
@JceId(13) val stShareData: ShareData?,
@JceId(14) val lFromInstId: Long?,
@JceId(15) val vRemarkOfSender: ByteArray?,
@JceId(16) val strFromMobile: String?,
@JceId(17) val strFromName: String?,
@JceId(18) val vNickName: List<String>?//,
//@SerialId(19) val stC2CTmpMsgHead: TempMsgHead?
) : JceStruct
@Serializable
internal class ShareData(
@SerialId(0) val pkgname: String = "",
@SerialId(1) val msgtail: String = "",
@SerialId(2) val picurl: String = "",
@SerialId(3) val url: String = ""
@JceId(0) val pkgname: String = "",
@JceId(1) val msgtail: String = "",
@JceId(2) val picurl: String = "",
@JceId(3) val url: String = ""
) : JceStruct
@Serializable
internal class TempMsgHead(
@SerialId(0) val c2c_type: Int? = 0,
@SerialId(1) val serviceType: Int? = 0
@JceId(0) val c2c_type: Int? = 0,
@JceId(1) val serviceType: Int? = 0
) : JceStruct
@Serializable
internal class CPicInfo(
@SerialId(0) val vPath: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(1) val vHost: ByteArray? = EMPTY_BYTE_ARRAY
@JceId(0) val vPath: ByteArray = EMPTY_BYTE_ARRAY,
@JceId(1) val vHost: ByteArray? = EMPTY_BYTE_ARRAY
) : JceStruct

View File

@ -9,38 +9,38 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
private val EMPTY_MAP = mapOf<String, String>()
@Serializable
internal class RequestPacket(
@SerialId(1) val iVersion: Short = 3,
@SerialId(2) val cPacketType: Byte = 0,
@SerialId(3) val iMessageType: Int = 0,
@SerialId(4) val iRequestId: Int,
@SerialId(5) val sServantName: String = "",
@SerialId(6) val sFuncName: String = "",
@SerialId(7) val sBuffer: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val iTimeout: Int? = 0,
@SerialId(9) val context: Map<String, String>? = EMPTY_MAP,
@SerialId(10) val status: Map<String, String>? = EMPTY_MAP
@JceId(1) val iVersion: Short? = 3,
@JceId(2) val cPacketType: Byte = 0,
@JceId(3) val iMessageType: Int = 0,
@JceId(4) val iRequestId: Int,
@JceId(5) val sServantName: String = "",
@JceId(6) val sFuncName: String = "",
@JceId(7) val sBuffer: ByteArray = EMPTY_BYTE_ARRAY,
@JceId(8) val iTimeout: Int? = 0,
@JceId(9) val context: Map<String, String>? = EMPTY_MAP,
@JceId(10) val status: Map<String, String>? = EMPTY_MAP
) : JceStruct
@Serializable
internal class RequestDataVersion3(
@SerialId(0) val map: Map<String, ByteArray> // 注意: ByteArray 不能直接放序列化的 JceStruct!! 要放类似 RequestDataStructSvcReqRegister 的
@JceId(0) val map: Map<String, ByteArray> // 注意: ByteArray 不能直接放序列化的 JceStruct!! 要放类似 RequestDataStructSvcReqRegister 的
) : JceStruct
@Serializable
internal class RequestDataVersion2(
@SerialId(0) val map: Map<String, Map<String, ByteArray>>
@JceId(0) val map: Map<String, Map<String, ByteArray>>
) : JceStruct
@Serializable
internal class RequestDataStructSvcReqRegister(
@SerialId(0) val struct: SvcReqRegister
@JceId(0) val struct: SvcReqRegister
) : JceStruct

View File

@ -9,14 +9,15 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
@Serializable
internal class RequestPushForceOffline(
@SerialId(0) val uin: Long,
@SerialId(1) val title: String? = "",
@SerialId(2) val tips: String? = "",
@SerialId(3) val sameDevice: Byte? = null
@JceId(0) val uin: Long,
@JceId(1) val title: String? = "",
@JceId(2) val tips: String? = "",
@JceId(3) val sameDevice: Byte? = null
) : JceStruct

View File

@ -9,47 +9,47 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
@Serializable
internal class SvcReqRegister(
@SerialId(0) val lUin: Long = 0L,
@SerialId(1) val lBid: Long = 0L,
@SerialId(2) val cConnType: Byte = 0,
@SerialId(3) val sOther: String = "",
@SerialId(4) val iStatus: Int = 11,
@SerialId(5) val bOnlinePush: Byte = 0,
@SerialId(6) val bIsOnline: Byte = 0,
@SerialId(7) val bIsShowOnline: Byte = 0,
@SerialId(8) val bKikPC: Byte = 0,
@SerialId(9) val bKikWeak: Byte = 0,
@SerialId(10) val timeStamp: Long = 0L,
@SerialId(11) val iOSVersion: Long = 0L,
@SerialId(12) val cNetType: Byte = 0,
@SerialId(13) val sBuildVer: String? = "",
@SerialId(14) val bRegType: Byte = 0,
@SerialId(15) val vecDevParam: ByteArray? = null,
@SerialId(16) val vecGuid: ByteArray? = null,
@SerialId(17) val iLocaleID: Int = 2052,
@SerialId(18) val bSlientPush: Byte = 0,
@SerialId(19) val strDevName: String? = null,
@SerialId(20) val strDevType: String? = null,
@SerialId(21) val strOSVer: String? = null,
@SerialId(22) val bOpenPush: Byte = 1,
@SerialId(23) val iLargeSeq: Long = 0L,
@SerialId(24) val iLastWatchStartTime: Long = 0L,
@SerialId(26) val uOldSSOIp: Long = 0L,
@SerialId(27) val uNewSSOIp: Long = 0L,
@SerialId(28) val sChannelNo: String? = null,
@SerialId(29) val lCpId: Long = 0L,
@SerialId(30) val strVendorName: String? = null,
@SerialId(31) val strVendorOSName: String? = null,
@SerialId(32) val strIOSIdfa: String? = null,
@SerialId(33) val bytes_0x769_reqbody: ByteArray? = null,
@SerialId(34) val bIsSetStatus: Byte = 0,
@SerialId(35) val vecServerBuf: ByteArray? = null,
@SerialId(36) val bSetMute: Byte = 0
@JceId(0) val lUin: Long = 0L,
@JceId(1) val lBid: Long = 0L,
@JceId(2) val cConnType: Byte = 0,
@JceId(3) val sOther: String = "",
@JceId(4) val iStatus: Int = 11,
@JceId(5) val bOnlinePush: Byte = 0,
@JceId(6) val bIsOnline: Byte = 0,
@JceId(7) val bIsShowOnline: Byte = 0,
@JceId(8) val bKikPC: Byte = 0,
@JceId(9) val bKikWeak: Byte = 0,
@JceId(10) val timeStamp: Long = 0L,
@JceId(11) val iOSVersion: Long = 0L,
@JceId(12) val cNetType: Byte = 0,
@JceId(13) val sBuildVer: String? = "",
@JceId(14) val bRegType: Byte = 0,
@JceId(15) val vecDevParam: ByteArray? = null,
@JceId(16) val vecGuid: ByteArray? = null,
@JceId(17) val iLocaleID: Int = 2052,
@JceId(18) val bSlientPush: Byte = 0,
@JceId(19) val strDevName: String? = null,
@JceId(20) val strDevType: String? = null,
@JceId(21) val strOSVer: String? = null,
@JceId(22) val bOpenPush: Byte = 1,
@JceId(23) val iLargeSeq: Long = 0L,
@JceId(24) val iLastWatchStartTime: Long = 0L,
@JceId(26) val uOldSSOIp: Long = 0L,
@JceId(27) val uNewSSOIp: Long = 0L,
@JceId(28) val sChannelNo: String? = null,
@JceId(29) val lCpId: Long = 0L,
@JceId(30) val strVendorName: String? = null,
@JceId(31) val strVendorOSName: String? = null,
@JceId(32) val strIOSIdfa: String? = null,
@JceId(33) val bytes_0x769_reqbody: ByteArray? = null,
@JceId(34) val bIsSetStatus: Byte = 0,
@JceId(35) val vecServerBuf: ByteArray? = null,
@JceId(36) val bSetMute: Byte = 0
// @SerialId(25) var vecBindUin: ArrayList<*>? = null // ?? 未知泛型
) : JceStruct

View File

@ -9,183 +9,183 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
@Serializable
internal class GetTroopListReqV2Simplify(
@SerialId(0) val uin: Long,
@SerialId(1) val getMSFMsgFlag: Byte? = null,
@SerialId(2) val vecCookies: ByteArray? = null,
@SerialId(3) val vecGroupInfo: List<StTroopNumSimplify>? = null,
@SerialId(4) val groupFlagExt: Byte? = null,
@SerialId(5) val shVersion: Int? = null,
@SerialId(6) val dwCompanyId: Long? = null,
@SerialId(7) val versionNum: Long? = null,
@SerialId(8) val getLongGroupName: Byte? = null
@JceId(0) val uin: Long,
@JceId(1) val getMSFMsgFlag: Byte? = null,
@JceId(2) val vecCookies: ByteArray? = null,
@JceId(3) val vecGroupInfo: List<StTroopNumSimplify>? = null,
@JceId(4) val groupFlagExt: Byte? = null,
@JceId(5) val shVersion: Int? = null,
@JceId(6) val dwCompanyId: Long? = null,
@JceId(7) val versionNum: Long? = null,
@JceId(8) val getLongGroupName: Byte? = null
) : JceStruct
@Serializable
internal class StTroopNumSimplify(
@SerialId(0) val groupCode: Long,
@SerialId(1) val dwGroupInfoSeq: Long? = null,
@SerialId(2) val dwGroupFlagExt: Long? = null,
@SerialId(3) val dwGroupRankSeq: Long? = null
@JceId(0) val groupCode: Long,
@JceId(1) val dwGroupInfoSeq: Long? = null,
@JceId(2) val dwGroupFlagExt: Long? = null,
@JceId(3) val dwGroupRankSeq: Long? = null
) : JceStruct
@Serializable
internal class GetTroopListRespV2(
@SerialId(0) val uin: Long,
@SerialId(1) val troopCount: Short,
@SerialId(2) val result: Int,
@SerialId(3) val errorCode: Short? = null,
@SerialId(4) val vecCookies: ByteArray? = null,
@SerialId(5) val vecTroopList: List<StTroopNum>? = null,
@SerialId(6) val vecTroopListDel: List<StTroopNum>? = null,
@SerialId(7) val vecTroopRank: List<StGroupRankInfo>? = null,
@SerialId(8) val vecFavGroup: List<StFavoriteGroup>? = null,
@SerialId(9) val vecTroopListExt: List<StTroopNum>? = null
@JceId(0) val uin: Long,
@JceId(1) val troopCount: Short,
@JceId(2) val result: Int,
@JceId(3) val errorCode: Short? = null,
@JceId(4) val vecCookies: ByteArray? = null,
@JceId(5) val vecTroopList: List<StTroopNum>? = null,
@JceId(6) val vecTroopListDel: List<StTroopNum>? = null,
@JceId(7) val vecTroopRank: List<StGroupRankInfo>? = null,
@JceId(8) val vecFavGroup: List<StFavoriteGroup>? = null,
@JceId(9) val vecTroopListExt: List<StTroopNum>? = null
) : JceStruct
@Serializable
internal class StTroopNum(
@SerialId(0) val groupUin: Long,
@SerialId(1) val groupCode: Long,
@SerialId(2) val flag: Byte? = null,
@SerialId(3) val dwGroupInfoSeq: Long? = null,
@SerialId(4) val groupName: String = "",
@SerialId(5) val groupMemo: String = "",
@SerialId(6) val dwGroupFlagExt: Long? = null,
@SerialId(7) val dwGroupRankSeq: Long? = null,
@SerialId(8) val dwCertificationType: Long? = null,
@SerialId(9) val dwShutUpTimestamp: Long? = null,
@SerialId(10) val dwMyShutUpTimestamp: Long? = null,
@SerialId(11) val dwCmdUinUinFlag: Long? = null,
@SerialId(12) val dwAdditionalFlag: Long? = null,
@SerialId(13) val dwGroupTypeFlag: Long? = null,
@SerialId(14) val dwGroupSecType: Long? = null,
@SerialId(15) val dwGroupSecTypeInfo: Long? = null,
@SerialId(16) val dwGroupClassExt: Long? = null,
@SerialId(17) val dwAppPrivilegeFlag: Long? = null,
@SerialId(18) val dwSubscriptionUin: Long? = null,
@SerialId(19) val dwMemberNum: Long? = null,
@SerialId(20) val dwMemberNumSeq: Long? = null,
@SerialId(21) val dwMemberCardSeq: Long? = null,
@SerialId(22) val dwGroupFlagExt3: Long? = null,
@SerialId(23) val dwGroupOwnerUin: Long,
@SerialId(24) val isConfGroup: Byte? = null,
@SerialId(25) val isModifyConfGroupFace: Byte? = null,
@SerialId(26) val isModifyConfGroupName: Byte? = null,
@SerialId(27) val dwCmduinJoinTime: Long? = null,
@SerialId(28) val ulCompanyId: Long? = null,
@SerialId(29) val dwMaxGroupMemberNum: Long? = null,
@SerialId(30) val dwCmdUinGroupMask: Long? = null,
@SerialId(31) val udwHLGuildAppid: Long? = null,
@SerialId(32) val udwHLGuildSubType: Long? = null,
@SerialId(33) val udwCmdUinRingtoneID: Long? = null,
@SerialId(34) val udwCmdUinFlagEx2: Long? = null
@JceId(0) val groupUin: Long,
@JceId(1) val groupCode: Long,
@JceId(2) val flag: Byte? = null,
@JceId(3) val dwGroupInfoSeq: Long? = null,
@JceId(4) val groupName: String = "",
@JceId(5) val groupMemo: String = "",
@JceId(6) val dwGroupFlagExt: Long? = null,
@JceId(7) val dwGroupRankSeq: Long? = null,
@JceId(8) val dwCertificationType: Long? = null,
@JceId(9) val dwShutUpTimestamp: Long? = null,
@JceId(10) val dwMyShutUpTimestamp: Long? = null,
@JceId(11) val dwCmdUinUinFlag: Long? = null,
@JceId(12) val dwAdditionalFlag: Long? = null,
@JceId(13) val dwGroupTypeFlag: Long? = null,
@JceId(14) val dwGroupSecType: Long? = null,
@JceId(15) val dwGroupSecTypeInfo: Long? = null,
@JceId(16) val dwGroupClassExt: Long? = null,
@JceId(17) val dwAppPrivilegeFlag: Long? = null,
@JceId(18) val dwSubscriptionUin: Long? = null,
@JceId(19) val dwMemberNum: Long? = null,
@JceId(20) val dwMemberNumSeq: Long? = null,
@JceId(21) val dwMemberCardSeq: Long? = null,
@JceId(22) val dwGroupFlagExt3: Long? = null,
@JceId(23) val dwGroupOwnerUin: Long,
@JceId(24) val isConfGroup: Byte? = null,
@JceId(25) val isModifyConfGroupFace: Byte? = null,
@JceId(26) val isModifyConfGroupName: Byte? = null,
@JceId(27) val dwCmduinJoinTime: Long? = null,
@JceId(28) val ulCompanyId: Long? = null,
@JceId(29) val dwMaxGroupMemberNum: Long? = null,
@JceId(30) val dwCmdUinGroupMask: Long? = null,
@JceId(31) val udwHLGuildAppid: Long? = null,
@JceId(32) val udwHLGuildSubType: Long? = null,
@JceId(33) val udwCmdUinRingtoneID: Long? = null,
@JceId(34) val udwCmdUinFlagEx2: Long? = null
) : JceStruct
@Serializable
internal class StGroupRankInfo(
@SerialId(0) val dwGroupCode: Long,
@SerialId(1) val groupRankSysFlag: Byte? = null,
@SerialId(2) val groupRankUserFlag: Byte? = null,
@SerialId(3) val vecRankMap: List<StLevelRankPair>? = null,
@SerialId(4) val dwGroupRankSeq: Long? = null,
@SerialId(5) val ownerName: String? = "",
@SerialId(6) val adminName: String? = "",
@SerialId(7) val dwOfficeMode: Long? = null
@JceId(0) val dwGroupCode: Long,
@JceId(1) val groupRankSysFlag: Byte? = null,
@JceId(2) val groupRankUserFlag: Byte? = null,
@JceId(3) val vecRankMap: List<StLevelRankPair>? = null,
@JceId(4) val dwGroupRankSeq: Long? = null,
@JceId(5) val ownerName: String? = "",
@JceId(6) val adminName: String? = "",
@JceId(7) val dwOfficeMode: Long? = null
) : JceStruct
@Serializable
internal class StFavoriteGroup(
@SerialId(0) val dwGroupCode: Long,
@SerialId(1) val dwTimestamp: Long? = null,
@SerialId(2) val dwSnsFlag: Long? = 1L,
@SerialId(3) val dwOpenTimestamp: Long? = null
@JceId(0) val dwGroupCode: Long,
@JceId(1) val dwTimestamp: Long? = null,
@JceId(2) val dwSnsFlag: Long? = 1L,
@JceId(3) val dwOpenTimestamp: Long? = null
) : JceStruct
@Serializable
internal class StLevelRankPair(
@SerialId(0) val dwLevel: Long? = null,
@SerialId(1) val rank: String? = ""
@JceId(0) val dwLevel: Long? = null,
@JceId(1) val rank: String? = ""
) : JceStruct
@Serializable
internal class GetTroopMemberListReq(
@SerialId(0) val uin: Long,
@SerialId(1) val groupCode: Long,
@SerialId(2) val nextUin: Long,
@SerialId(3) val groupUin: Long,
@SerialId(4) val version: Long? = null,
@SerialId(5) val reqType: Long? = null,
@SerialId(6) val getListAppointTime: Long? = null,
@SerialId(7) val richCardNameVer: Byte? = null
@JceId(0) val uin: Long,
@JceId(1) val groupCode: Long,
@JceId(2) val nextUin: Long,
@JceId(3) val groupUin: Long,
@JceId(4) val version: Long? = null,
@JceId(5) val reqType: Long? = null,
@JceId(6) val getListAppointTime: Long? = null,
@JceId(7) val richCardNameVer: Byte? = null
) : JceStruct
@Serializable
internal class GetTroopMemberListResp(
@SerialId(0) val uin: Long,
@SerialId(1) val groupCode: Long,
@SerialId(2) val groupUin: Long,
@SerialId(3) val vecTroopMember: List<StTroopMemberInfo>,
@SerialId(4) val nextUin: Long,
@SerialId(5) val result: Int,
@SerialId(6) val errorCode: Short? = null,
@SerialId(7) val officeMode: Long? = null,
@SerialId(8) val nextGetTime: Long? = null
@JceId(0) val uin: Long,
@JceId(1) val groupCode: Long,
@JceId(2) val groupUin: Long,
@JceId(3) val vecTroopMember: List<StTroopMemberInfo>,
@JceId(4) val nextUin: Long,
@JceId(5) val result: Int,
@JceId(6) val errorCode: Short? = null,
@JceId(7) val officeMode: Long? = null,
@JceId(8) val nextGetTime: Long? = null
) : JceStruct
@Serializable
internal class StTroopMemberInfo(
@SerialId(0) val memberUin: Long,
@SerialId(1) val faceId: Short,
@SerialId(2) val age: Byte,
@SerialId(3) val gender: Byte,
@SerialId(4) val nick: String = "",
@SerialId(5) val status: Byte = 20,
@SerialId(6) val sShowName: String? = null,
@SerialId(8) val sName: String? = null,
@SerialId(9) val cGender: Byte? = null,
@SerialId(10) val sPhone: String? = "",
@SerialId(11) val sEmail: String? = "",
@SerialId(12) val sMemo: String? = "",
@SerialId(13) val autoRemark: String? = "",
@SerialId(14) val dwMemberLevel: Long? = null,
@SerialId(15) val dwJoinTime: Long? = null,
@SerialId(16) val dwLastSpeakTime: Long? = null,
@SerialId(17) val dwCreditLevel: Long? = null,
@SerialId(18) val dwFlag: Long? = null,
@SerialId(19) val dwFlagExt: Long? = null,
@SerialId(20) val dwPoint: Long? = null,
@SerialId(21) val concerned: Byte? = null,
@SerialId(22) val shielded: Byte? = null,
@SerialId(23) val sSpecialTitle: String? = "",
@SerialId(24) val dwSpecialTitleExpireTime: Long? = null,
@SerialId(25) val job: String? = "",
@SerialId(26) val apolloFlag: Byte? = null,
@SerialId(27) val dwApolloTimestamp: Long? = null,
@SerialId(28) val dwGlobalGroupLevel: Long? = null,
@SerialId(29) val dwTitleId: Long? = null,
@SerialId(30) val dwShutupTimestap: Long? = null,
@SerialId(31) val dwGlobalGroupPoint: Long? = null,
@SerialId(32) val qzusrinfo: QzoneUserInfo? = null,
@SerialId(33) val richCardNameVer: Byte? = null,
@SerialId(34) val dwVipType: Long? = null,
@SerialId(35) val dwVipLevel: Long? = null,
@SerialId(36) val dwBigClubLevel: Long? = null,
@SerialId(37) val dwBigClubFlag: Long? = null,
@SerialId(38) val dwNameplate: Long? = null,
@SerialId(39) val vecGroupHonor: ByteArray? = null
@JceId(0) val memberUin: Long,
@JceId(1) val faceId: Short,
@JceId(2) val age: Byte,
@JceId(3) val gender: Byte,
@JceId(4) val nick: String = "",
@JceId(5) val status: Byte = 20,
@JceId(6) val sShowName: String? = null,
@JceId(8) val sName: String? = null,
@JceId(9) val cGender: Byte? = null,
@JceId(10) val sPhone: String? = "",
@JceId(11) val sEmail: String? = "",
@JceId(12) val sMemo: String? = "",
@JceId(13) val autoRemark: String? = "",
@JceId(14) val dwMemberLevel: Long? = null,
@JceId(15) val dwJoinTime: Long? = null,
@JceId(16) val dwLastSpeakTime: Long? = null,
@JceId(17) val dwCreditLevel: Long? = null,
@JceId(18) val dwFlag: Long? = null,
@JceId(19) val dwFlagExt: Long? = null,
@JceId(20) val dwPoint: Long? = null,
@JceId(21) val concerned: Byte? = null,
@JceId(22) val shielded: Byte? = null,
@JceId(23) val sSpecialTitle: String? = "",
@JceId(24) val dwSpecialTitleExpireTime: Long? = null,
@JceId(25) val job: String? = "",
@JceId(26) val apolloFlag: Byte? = null,
@JceId(27) val dwApolloTimestamp: Long? = null,
@JceId(28) val dwGlobalGroupLevel: Long? = null,
@JceId(29) val dwTitleId: Long? = null,
@JceId(30) val dwShutupTimestap: Long? = null,
@JceId(31) val dwGlobalGroupPoint: Long? = null,
@JceId(32) val qzusrinfo: QzoneUserInfo? = null,
@JceId(33) val richCardNameVer: Byte? = null,
@JceId(34) val dwVipType: Long? = null,
@JceId(35) val dwVipLevel: Long? = null,
@JceId(36) val dwBigClubLevel: Long? = null,
@JceId(37) val dwBigClubFlag: Long? = null,
@JceId(38) val dwNameplate: Long? = null,
@JceId(39) val vecGroupHonor: ByteArray? = null
) : JceStruct
@Serializable
internal class QzoneUserInfo(
@SerialId(0) val eStarState: Int? = null,
@SerialId(1) val extendInfo: Map<String, String>? = null
@JceId(0) val eStarState: Int? = null,
@JceId(1) val extendInfo: Map<String, String>? = null
) : JceStruct

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@ -18,118 +18,118 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
internal class Cmd0x352 : ProtoBuf {
@Serializable
class DelImgReq(
@SerialId(1) val srcUin: Long = 0L,
@SerialId(2) val dstUin: Long = 0L,
@SerialId(3) val reqTerm: Int = 0,
@SerialId(4) val reqPlatformType: Int = 0,
@SerialId(5) val buType: Int = 0,
@SerialId(6) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val picWidth: Int = 0,
@SerialId(9) val picHeight: Int = 0
@ProtoId(1) val srcUin: Long = 0L,
@ProtoId(2) val dstUin: Long = 0L,
@ProtoId(3) val reqTerm: Int = 0,
@ProtoId(4) val reqPlatformType: Int = 0,
@ProtoId(5) val buType: Int = 0,
@ProtoId(6) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(7) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(8) val picWidth: Int = 0,
@ProtoId(9) val picHeight: Int = 0
) : ProtoBuf
@Serializable
class DelImgRsp(
@SerialId(1) val result: Int = 0,
@SerialId(2) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val fileResid: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val result: Int = 0,
@ProtoId(2) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val fileResid: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class GetImgUrlReq(
@SerialId(1) val srcUin: Long = 0L,
@SerialId(2) val dstUin: Long = 0L,
@SerialId(3) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val urlFlag: Int = 0,
@SerialId(6) val urlType: Int = 0,
@SerialId(7) val reqTerm: Int = 0,
@SerialId(8) val reqPlatformType: Int = 0,
@SerialId(9) val srcFileType: Int = 0,
@SerialId(10) val innerIp: Int = 0,
@SerialId(11) val boolAddressBook: Boolean = false,
@SerialId(12) val buType: Int = 0,
@SerialId(13) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(14) val picUpTimestamp: Int = 0,
@SerialId(15) val reqTransferType: Int = 0
@ProtoId(1) val srcUin: Long = 0L,
@ProtoId(2) val dstUin: Long = 0L,
@ProtoId(3) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val urlFlag: Int = 0,
@ProtoId(6) val urlType: Int = 0,
@ProtoId(7) val reqTerm: Int = 0,
@ProtoId(8) val reqPlatformType: Int = 0,
@ProtoId(9) val srcFileType: Int = 0,
@ProtoId(10) val innerIp: Int = 0,
@ProtoId(11) val boolAddressBook: Boolean = false,
@ProtoId(12) val buType: Int = 0,
@ProtoId(13) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(14) val picUpTimestamp: Int = 0,
@ProtoId(15) val reqTransferType: Int = 0
) : ProtoBuf
@Serializable
class GetImgUrlRsp(
@SerialId(1) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val clientIp: Int = 0,
@SerialId(3) val result: Int = 0,
@SerialId(4) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val bytesThumbDownUrl: List<ByteArray>? = null,
@SerialId(6) val bytesOriginalDownUrl: List<ByteArray>? = null,
@SerialId(7) val msgImgInfo: ImgInfo? = null,
@SerialId(8) val uint32DownIp: List<Int>? = null,
@SerialId(9) val uint32DownPort: List<Int>? = null,
@SerialId(10) val thumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val originalDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(13) val bytesBigDownUrl: List<ByteArray>? = null,
@SerialId(14) val bigDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(15) val bigThumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(16) val httpsUrlFlag: Int = 0,
@SerialId(26) val msgDownIp6: List<IPv6Info>? = null,
@SerialId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val clientIp: Int = 0,
@ProtoId(3) val result: Int = 0,
@ProtoId(4) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val bytesThumbDownUrl: List<ByteArray>? = null,
@ProtoId(6) val bytesOriginalDownUrl: List<ByteArray>? = null,
@ProtoId(7) val msgImgInfo: ImgInfo? = null,
@ProtoId(8) val uint32DownIp: List<Int>? = null,
@ProtoId(9) val uint32DownPort: List<Int>? = null,
@ProtoId(10) val thumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(11) val originalDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(12) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(13) val bytesBigDownUrl: List<ByteArray>? = null,
@ProtoId(14) val bigDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(15) val bigThumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(16) val httpsUrlFlag: Int = 0,
@ProtoId(26) val msgDownIp6: List<IPv6Info>? = null,
@ProtoId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Suppress("ArrayInDataClass")
@Serializable
data class ImgInfo(
@SerialId(1) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val fileType: Int = 0,
@SerialId(3) val fileSize: Long = 0L,
@SerialId(4) val fileWidth: Int = 0,
@SerialId(5) val fileHeight: Int = 0,
@SerialId(6) val fileFlag: Long = 0L,
@SerialId(7) val fileCutPos: Int = 0
@ProtoId(1) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val fileType: Int = 0,
@ProtoId(3) val fileSize: Long = 0L,
@ProtoId(4) val fileWidth: Int = 0,
@ProtoId(5) val fileHeight: Int = 0,
@ProtoId(6) val fileFlag: Long = 0L,
@ProtoId(7) val fileCutPos: Int = 0
) : ProtoBuf
@Serializable
class IPv6Info(
@SerialId(1) val ip6: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val port: Int = 0
@ProtoId(1) val ip6: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val port: Int = 0
) : ProtoBuf
@Serializable
class ReqBody(
@SerialId(1) val subcmd: Int = 0, //2是GetImgUrlReq 1是UploadImgReq
@SerialId(2) val msgTryupImgReq: List<TryUpImgReq>? = null,// optional
@SerialId(3) val msgGetimgUrlReq: List<GetImgUrlReq>? = null,// optional
@SerialId(4) val msgDelImgReq: List<DelImgReq>? = null,
@SerialId(10) val netType: Int = 3// 数据网络=5
@ProtoId(1) val subcmd: Int = 0, //2是GetImgUrlReq 1是UploadImgReq
@ProtoId(2) val msgTryupImgReq: List<TryUpImgReq>? = null,// optional
@ProtoId(3) val msgGetimgUrlReq: List<GetImgUrlReq>? = null,// optional
@ProtoId(4) val msgDelImgReq: List<DelImgReq>? = null,
@ProtoId(10) val netType: Int = 3// 数据网络=5
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1) val subcmd: Int = 0,
@SerialId(2) val msgTryupImgRsp: List<TryUpImgRsp>? = null,
@SerialId(3) val msgGetimgUrlRsp: List<GetImgUrlRsp>? = null,
@SerialId(4) val boolNewBigchan: Boolean = false,
@SerialId(5) val msgDelImgRsp: List<DelImgRsp>? = null,
@SerialId(10) val failMsg: String? = ""
@ProtoId(1) val subcmd: Int = 0,
@ProtoId(2) val msgTryupImgRsp: List<TryUpImgRsp>? = null,
@ProtoId(3) val msgGetimgUrlRsp: List<GetImgUrlRsp>? = null,
@ProtoId(4) val boolNewBigchan: Boolean = false,
@ProtoId(5) val msgDelImgRsp: List<DelImgRsp>? = null,
@ProtoId(10) val failMsg: String? = ""
) : ProtoBuf
@Serializable
internal class TryUpImgReq(
@SerialId(1) val srcUin: Int,
@SerialId(2) val dstUin: Int,
@SerialId(3) val fileId: Int = 0,//从0开始的自增数貌似有一个连接就要自增1, 但是又会重置回0
@SerialId(4) val fileMd5: ByteArray,
@SerialId(5) val fileSize: Int,
@SerialId(6) val fileName: String,//默认为md5+".jpg"
@SerialId(7) val srcTerm: Int = 5,
@SerialId(8) val platformType: Int = 9,
@SerialId(9) val innerIP: Int = 0,
@SerialId(10) val addressBook: Int = 0,//chatType == 1006为1 我觉得发0没问题
@SerialId(11) val retry: Int = 0,//default
@SerialId(12) val buType: Int = 1,//1或96 不确定
@SerialId(13) val imgOriginal: Int,//是否为原图
@SerialId(14) val imgWidth: Int,
@SerialId(15) val imgHeight: Int,
@ProtoId(1) val srcUin: Int,
@ProtoId(2) val dstUin: Int,
@ProtoId(3) val fileId: Int = 0,//从0开始的自增数貌似有一个连接就要自增1, 但是又会重置回0
@ProtoId(4) val fileMd5: ByteArray,
@ProtoId(5) val fileSize: Int,
@ProtoId(6) val fileName: String,//默认为md5+".jpg"
@ProtoId(7) val srcTerm: Int = 5,
@ProtoId(8) val platformType: Int = 9,
@ProtoId(9) val innerIP: Int = 0,
@ProtoId(10) val addressBook: Int = 0,//chatType == 1006为1 我觉得发0没问题
@ProtoId(11) val retry: Int = 0,//default
@ProtoId(12) val buType: Int = 1,//1或96 不确定
@ProtoId(13) val imgOriginal: Int,//是否为原图
@ProtoId(14) val imgWidth: Int,
@ProtoId(15) val imgHeight: Int,
/**
* ImgType:
* JPG: 1000
@ -140,50 +140,50 @@ internal class Cmd0x352 : ProtoBuf {
* APNG: 2001
* SHARPP: 1004
*/
@SerialId(16) val imgType: Int = 1000,
@SerialId(17) val buildVer: String = "8.2.7.4410",//版本号
@SerialId(18) val fileIndex: ByteArray = EMPTY_BYTE_ARRAY,//default
@SerialId(19) val fileStoreDays: Int = 0,//default
@SerialId(20) val stepFlag: Int = 0,//default
@SerialId(21) val rejectTryFast: Int = 0,//bool
@SerialId(22) val srvUpload: Int = 1,//typeHotPic[1/2/3]
@SerialId(23) val transferUrl: ByteArray = EMPTY_BYTE_ARRAY//rawDownloadUrl, 如果没有就是EMPTY_BYTE_ARRAY
@ProtoId(16) val imgType: Int = 1000,
@ProtoId(17) val buildVer: String = "8.2.7.4410",//版本号
@ProtoId(18) val fileIndex: ByteArray = EMPTY_BYTE_ARRAY,//default
@ProtoId(19) val fileStoreDays: Int = 0,//default
@ProtoId(20) val stepFlag: Int = 0,//default
@ProtoId(21) val rejectTryFast: Int = 0,//bool
@ProtoId(22) val srvUpload: Int = 1,//typeHotPic[1/2/3]
@ProtoId(23) val transferUrl: ByteArray = EMPTY_BYTE_ARRAY//rawDownloadUrl, 如果没有就是EMPTY_BYTE_ARRAY
) : ImgReq
@Serializable
class TryUpImgRsp(
@SerialId(1) val fileId: Long = 0L,
@SerialId(2) val clientIp: Int = 0,
@SerialId(3) val result: Int = 0,
@SerialId(4) val failMsg: String? = "",
@SerialId(5) val boolFileExit: Boolean = false,
@SerialId(6) val msgImgInfo: ImgInfo? = null,
@SerialId(7) val uint32UpIp: List<Int>? = null,
@SerialId(8) val uint32UpPort: List<Int>? = null,
@SerialId(9) val upUkey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val upResid: String = "",
@SerialId(11) val upUuid: String = "",
@SerialId(12) val upOffset: Long = 0L,
@SerialId(13) val blockSize: Long = 0L,
@SerialId(14) val encryptDstip: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(15) val roamdays: Int = 0,
@SerialId(26) val msgUpIp6: List<IPv6Info>? = null,
@SerialId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(60) val thumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(61) val originalDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(62) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(64) val bigDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(65) val bigThumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(66) val httpsUrlFlag: Int = 0,
@SerialId(1001) val msgInfo4busi: TryUpInfo4Busi? = null
@ProtoId(1) val fileId: Long = 0L,
@ProtoId(2) val clientIp: Int = 0,
@ProtoId(3) val result: Int = 0,
@ProtoId(4) val failMsg: String? = "",
@ProtoId(5) val boolFileExit: Boolean = false,
@ProtoId(6) val msgImgInfo: ImgInfo? = null,
@ProtoId(7) val uint32UpIp: List<Int>? = null,
@ProtoId(8) val uint32UpPort: List<Int>? = null,
@ProtoId(9) val upUkey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(10) val upResid: String = "",
@ProtoId(11) val upUuid: String = "",
@ProtoId(12) val upOffset: Long = 0L,
@ProtoId(13) val blockSize: Long = 0L,
@ProtoId(14) val encryptDstip: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(15) val roamdays: Int = 0,
@ProtoId(26) val msgUpIp6: List<IPv6Info>? = null,
@ProtoId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(60) val thumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(61) val originalDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(62) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(64) val bigDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(65) val bigThumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(66) val httpsUrlFlag: Int = 0,
@ProtoId(1001) val msgInfo4busi: TryUpInfo4Busi? = null
) : ProtoBuf
@Serializable
class TryUpInfo4Busi(
@SerialId(1) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val thumbDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val originalDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val bigDownUrl: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val thumbDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val originalDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val bigDownUrl: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
}

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@ -18,141 +18,141 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
internal class Cmd0x388 : ProtoBuf {
@Serializable
class DelImgReq(
@SerialId(1) val srcUin: Long = 0L,
@SerialId(2) val dstUin: Long = 0L,
@SerialId(3) val reqTerm: Int = 0,
@SerialId(4) val reqPlatformType: Int = 0,
@SerialId(5) val buType: Int = 0,
@SerialId(6) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val picWidth: Int = 0,
@SerialId(9) val picHeight: Int = 0
@ProtoId(1) val srcUin: Long = 0L,
@ProtoId(2) val dstUin: Long = 0L,
@ProtoId(3) val reqTerm: Int = 0,
@ProtoId(4) val reqPlatformType: Int = 0,
@ProtoId(5) val buType: Int = 0,
@ProtoId(6) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(7) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(8) val picWidth: Int = 0,
@ProtoId(9) val picHeight: Int = 0
) : ProtoBuf
@Serializable
class DelImgRsp(
@SerialId(1) val result: Int = 0,
@SerialId(2) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val fileResid: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val result: Int = 0,
@ProtoId(2) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val fileResid: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ExpRoamExtendInfo(
@SerialId(1) val resid: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val resid: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ExpRoamPicInfo(
@SerialId(1) val shopFlag: Int = 0,
@SerialId(2) val pkgId: Int = 0,
@SerialId(3) val picId: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val shopFlag: Int = 0,
@ProtoId(2) val pkgId: Int = 0,
@ProtoId(3) val picId: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ExtensionCommPicTryUp(
@SerialId(1) val bytesExtinfo: List<ByteArray>? = null
@ProtoId(1) val bytesExtinfo: List<ByteArray>? = null
) : ProtoBuf
@Serializable
class ExtensionExpRoamTryUp(
@SerialId(1) val msgExproamPicInfo: List<ExpRoamPicInfo>? = null
@ProtoId(1) val msgExproamPicInfo: List<ExpRoamPicInfo>? = null
) : ProtoBuf
@Serializable
class GetImgUrlReq(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val dstUin: Long = 0L,
@SerialId(3) val fileid: Long = 0L,
@SerialId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val urlFlag: Int = 0,
@SerialId(6) val urlType: Int = 0,
@SerialId(7) val reqTerm: Int = 0,
@SerialId(8) val reqPlatformType: Int = 0,
@SerialId(9) val innerIp: Int = 0,
@SerialId(10) val buType: Int = 0,
@SerialId(11) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val fileId: Long = 0L,
@SerialId(13) val fileSize: Long = 0L,
@SerialId(14) val originalPic: Int = 0,
@SerialId(15) val retryReq: Int = 0,
@SerialId(16) val fileHeight: Int = 0,
@SerialId(17) val fileWidth: Int = 0,
@SerialId(18) val picType: Int = 0,
@SerialId(19) val picUpTimestamp: Int = 0,
@SerialId(20) val reqTransferType: Int = 0
@ProtoId(1) val groupCode: Long = 0L,
@ProtoId(2) val dstUin: Long = 0L,
@ProtoId(3) val fileid: Long = 0L,
@ProtoId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val urlFlag: Int = 0,
@ProtoId(6) val urlType: Int = 0,
@ProtoId(7) val reqTerm: Int = 0,
@ProtoId(8) val reqPlatformType: Int = 0,
@ProtoId(9) val innerIp: Int = 0,
@ProtoId(10) val buType: Int = 0,
@ProtoId(11) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(12) val fileId: Long = 0L,
@ProtoId(13) val fileSize: Long = 0L,
@ProtoId(14) val originalPic: Int = 0,
@ProtoId(15) val retryReq: Int = 0,
@ProtoId(16) val fileHeight: Int = 0,
@ProtoId(17) val fileWidth: Int = 0,
@ProtoId(18) val picType: Int = 0,
@ProtoId(19) val picUpTimestamp: Int = 0,
@ProtoId(20) val reqTransferType: Int = 0
) : ProtoBuf
@Serializable
class GetImgUrlRsp(
@SerialId(1) val fileid: Long = 0L,
@SerialId(2) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val result: Int = 0,
@SerialId(4) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val msgImgInfo: ImgInfo? = null,
@SerialId(6) val bytesThumbDownUrl: List<ByteArray>? = null,
@SerialId(7) val bytesOriginalDownUrl: List<ByteArray>? = null,
@SerialId(8) val bytesBigDownUrl: List<ByteArray>? = null,
@SerialId(9) val uint32DownIp: List<Int>? = null,
@SerialId(10) val uint32DownPort: List<Int>? = null,
@SerialId(11) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val thumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(13) val originalDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(14) val bigDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(15) val fileId: Long = 0L,
@SerialId(16) val autoDownType: Int = 0,
@SerialId(17) val uint32OrderDownType: List<Int>? = null,
@SerialId(19) val bigThumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(20) val httpsUrlFlag: Int = 0,
@SerialId(26) val msgDownIp6: List<IPv6Info>? = null,
@SerialId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val fileid: Long = 0L,
@ProtoId(2) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val result: Int = 0,
@ProtoId(4) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val msgImgInfo: ImgInfo? = null,
@ProtoId(6) val bytesThumbDownUrl: List<ByteArray>? = null,
@ProtoId(7) val bytesOriginalDownUrl: List<ByteArray>? = null,
@ProtoId(8) val bytesBigDownUrl: List<ByteArray>? = null,
@ProtoId(9) val uint32DownIp: List<Int>? = null,
@ProtoId(10) val uint32DownPort: List<Int>? = null,
@ProtoId(11) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(12) val thumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(13) val originalDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(14) val bigDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(15) val fileId: Long = 0L,
@ProtoId(16) val autoDownType: Int = 0,
@ProtoId(17) val uint32OrderDownType: List<Int>? = null,
@ProtoId(19) val bigThumbDownPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(20) val httpsUrlFlag: Int = 0,
@ProtoId(26) val msgDownIp6: List<IPv6Info>? = null,
@ProtoId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class GetPttUrlReq(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val dstUin: Long = 0L,
@SerialId(3) val fileid: Long = 0L,
@SerialId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val reqTerm: Int = 0,
@SerialId(6) val reqPlatformType: Int = 0,
@SerialId(7) val innerIp: Int = 0,
@SerialId(8) val buType: Int = 0,
@SerialId(9) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val fileId: Long = 0L,
@SerialId(11) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val codec: Int = 0,
@SerialId(13) val buId: Int = 0,
@SerialId(14) val reqTransferType: Int = 0,
@SerialId(15) val isAuto: Int = 0
@ProtoId(1) val groupCode: Long = 0L,
@ProtoId(2) val dstUin: Long = 0L,
@ProtoId(3) val fileid: Long = 0L,
@ProtoId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val reqTerm: Int = 0,
@ProtoId(6) val reqPlatformType: Int = 0,
@ProtoId(7) val innerIp: Int = 0,
@ProtoId(8) val buType: Int = 0,
@ProtoId(9) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(10) val fileId: Long = 0L,
@ProtoId(11) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(12) val codec: Int = 0,
@ProtoId(13) val buId: Int = 0,
@ProtoId(14) val reqTransferType: Int = 0,
@ProtoId(15) val isAuto: Int = 0
) : ProtoBuf
@Serializable
class GetPttUrlRsp(
@SerialId(1) val fileid: Long = 0L,
@SerialId(2) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val result: Int = 0,
@SerialId(4) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val bytesDownUrl: List<ByteArray>? = null,
@SerialId(6) val uint32DownIp: List<Int>? = null,
@SerialId(7) val uint32DownPort: List<Int>? = null,
@SerialId(8) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val downPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val fileId: Long = 0L,
@SerialId(11) val transferType: Int = 0,
@SerialId(12) val allowRetry: Int = 0,
@SerialId(26) val msgDownIp6: List<IPv6Info>? = null,
@SerialId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(28) val strDomain: String = ""
@ProtoId(1) val fileid: Long = 0L,
@ProtoId(2) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val result: Int = 0,
@ProtoId(4) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val bytesDownUrl: List<ByteArray>? = null,
@ProtoId(6) val uint32DownIp: List<Int>? = null,
@ProtoId(7) val uint32DownPort: List<Int>? = null,
@ProtoId(8) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(9) val downPara: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(10) val fileId: Long = 0L,
@ProtoId(11) val transferType: Int = 0,
@ProtoId(12) val allowRetry: Int = 0,
@ProtoId(26) val msgDownIp6: List<IPv6Info>? = null,
@ProtoId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(28) val strDomain: String = ""
) : ProtoBuf
@Suppress("ArrayInDataClass")
@Serializable
data class ImgInfo(
@SerialId(1) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val fileType: Int = 0,
@SerialId(3) val fileSize: Long = 0L,
@SerialId(4) val fileWidth: Int = 0,
@SerialId(5) val fileHeight: Int = 0
@ProtoId(1) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val fileType: Int = 0,
@ProtoId(3) val fileSize: Long = 0L,
@ProtoId(4) val fileWidth: Int = 0,
@ProtoId(5) val fileHeight: Int = 0
) : ProtoBuf {
override fun toString(): String {
return "ImgInfo(fileMd5=${fileMd5.contentToString()}, fileType=$fileType, fileSize=$fileSize, fileWidth=$fileWidth, fileHeight=$fileHeight)"
@ -161,128 +161,128 @@ internal class Cmd0x388 : ProtoBuf {
@Serializable
class IPv6Info(
@SerialId(1) val ip6: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val port: Int = 0
@ProtoId(1) val ip6: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val port: Int = 0
) : ProtoBuf
@Serializable
class PicSize(
@SerialId(1) val original: Int = 0,
@SerialId(2) val thumb: Int = 0,
@SerialId(3) val high: Int = 0
@ProtoId(1) val original: Int = 0,
@ProtoId(2) val thumb: Int = 0,
@ProtoId(3) val high: Int = 0
) : ProtoBuf
@Serializable
class ReqBody(
@SerialId(1) val netType: Int = 0,
@SerialId(2) val subcmd: Int = 0,
@SerialId(3) val msgTryupImgReq: List<TryUpImgReq>? = null,
@SerialId(4) val msgGetimgUrlReq: List<GetImgUrlReq>? = null,
@SerialId(5) val msgTryupPttReq: List<TryUpPttReq>? = null,
@SerialId(6) val msgGetpttUrlReq: List<GetPttUrlReq>? = null,
@SerialId(7) val commandId: Int = 0,
@SerialId(8) val msgDelImgReq: List<DelImgReq>? = null,
@SerialId(1001) val extension: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val netType: Int = 0,
@ProtoId(2) val subcmd: Int = 0,
@ProtoId(3) val msgTryupImgReq: List<TryUpImgReq>? = null,
@ProtoId(4) val msgGetimgUrlReq: List<GetImgUrlReq>? = null,
@ProtoId(5) val msgTryupPttReq: List<TryUpPttReq>? = null,
@ProtoId(6) val msgGetpttUrlReq: List<GetPttUrlReq>? = null,
@ProtoId(7) val commandId: Int = 0,
@ProtoId(8) val msgDelImgReq: List<DelImgReq>? = null,
@ProtoId(1001) val extension: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1) val clientIp: Int = 0,
@SerialId(2) val subcmd: Int = 0,
@SerialId(3) val msgTryupImgRsp: List<TryUpImgRsp>? = null,
@SerialId(4) val msgGetimgUrlRsp: List<GetImgUrlRsp>? = null,
@SerialId(5) val msgTryupPttRsp: List<TryUpPttRsp>? = null,
@SerialId(6) val msgGetpttUrlRsp: List<GetPttUrlRsp>? = null,
@SerialId(7) val msgDelImgRsp: List<DelImgRsp>? = null
@ProtoId(1) val clientIp: Int = 0,
@ProtoId(2) val subcmd: Int = 0,
@ProtoId(3) val msgTryupImgRsp: List<TryUpImgRsp>? = null,
@ProtoId(4) val msgGetimgUrlRsp: List<GetImgUrlRsp>? = null,
@ProtoId(5) val msgTryupPttRsp: List<TryUpPttRsp>? = null,
@ProtoId(6) val msgGetpttUrlRsp: List<GetPttUrlRsp>? = null,
@ProtoId(7) val msgDelImgRsp: List<DelImgRsp>? = null
) : ProtoBuf
@Serializable
class TryUpImgReq(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val srcUin: Long = 0L,
@SerialId(3) val fileId: Long = 0L,
@SerialId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val fileSize: Long = 0L,
@SerialId(6) val fileName: String ="",
@SerialId(7) val srcTerm: Int = 0,
@SerialId(8) val platformType: Int = 0,
@SerialId(9) val buType: Int = 0,
@SerialId(10) val picWidth: Int = 0,
@SerialId(11) val picHeight: Int = 0,
@SerialId(12) val picType: Int = 0,
@SerialId(13) val buildVer: String = "",
@SerialId(14) val innerIp: Int = 0,
@SerialId(15) val appPicType: Int = 0,
@SerialId(16) val originalPic: Int = 0,
@SerialId(17) val fileIndex: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(18) val dstUin: Long = 0L,
@SerialId(19) val srvUpload: Int = 0,
@SerialId(20) val transferUrl: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val groupCode: Long = 0L,
@ProtoId(2) val srcUin: Long = 0L,
@ProtoId(3) val fileId: Long = 0L,
@ProtoId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val fileSize: Long = 0L,
@ProtoId(6) val fileName: String = "",
@ProtoId(7) val srcTerm: Int = 0,
@ProtoId(8) val platformType: Int = 0,
@ProtoId(9) val buType: Int = 0,
@ProtoId(10) val picWidth: Int = 0,
@ProtoId(11) val picHeight: Int = 0,
@ProtoId(12) val picType: Int = 0,
@ProtoId(13) val buildVer: String = "",
@ProtoId(14) val innerIp: Int = 0,
@ProtoId(15) val appPicType: Int = 0,
@ProtoId(16) val originalPic: Int = 0,
@ProtoId(17) val fileIndex: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(18) val dstUin: Long = 0L,
@ProtoId(19) val srvUpload: Int = 0,
@ProtoId(20) val transferUrl: ByteArray = EMPTY_BYTE_ARRAY
) : ImgReq
@Serializable
class TryUpImgRsp(
@SerialId(1) val fileId: Long = 0L,
@SerialId(2) val result: Int = 0,
@SerialId(3) val failMsg: String = "",
@SerialId(4) val boolFileExit: Boolean = false,
@SerialId(5) val msgImgInfo: ImgInfo? = null,
@SerialId(6) val uint32UpIp: List<Int>? = null,
@SerialId(7) val uint32UpPort: List<Int>? = null,
@SerialId(8) val upUkey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val fileid: Long = 0L,
@SerialId(10) val upOffset: Long = 0L,
@SerialId(11) val blockSize: Long = 0L,
@SerialId(12) val boolNewBigChan: Boolean = false,
@SerialId(26) val msgUpIp6: List<IPv6Info>? = null,
@SerialId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(1001) val msgInfo4busi: TryUpInfo4Busi? = null
@ProtoId(1) val fileId: Long = 0L,
@ProtoId(2) val result: Int = 0,
@ProtoId(3) val failMsg: String = "",
@ProtoId(4) val boolFileExit: Boolean = false,
@ProtoId(5) val msgImgInfo: ImgInfo? = null,
@ProtoId(6) val uint32UpIp: List<Int>? = null,
@ProtoId(7) val uint32UpPort: List<Int>? = null,
@ProtoId(8) val upUkey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(9) val fileid: Long = 0L,
@ProtoId(10) val upOffset: Long = 0L,
@ProtoId(11) val blockSize: Long = 0L,
@ProtoId(12) val boolNewBigChan: Boolean = false,
@ProtoId(26) val msgUpIp6: List<IPv6Info>? = null,
@ProtoId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(1001) val msgInfo4busi: TryUpInfo4Busi? = null
) : ProtoBuf
@Serializable
class TryUpInfo4Busi(
@SerialId(1) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val thumbDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val originalDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val bigDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val fileResid: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val downDomain: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val thumbDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val originalDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val bigDownUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val fileResid: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class TryUpPttReq(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val srcUin: Long = 0L,
@SerialId(3) val fileId: Long = 0L,
@SerialId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val fileSize: Long = 0L,
@SerialId(6) val fileName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val srcTerm: Int = 0,
@SerialId(8) val platformType: Int = 0,
@SerialId(9) val buType: Int = 0,
@SerialId(10) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val innerIp: Int = 0,
@SerialId(12) val voiceLength: Int = 0,
@SerialId(13) val boolNewUpChan: Boolean = false,
@SerialId(14) val codec: Int = 0,
@SerialId(15) val voiceType: Int = 0,
@SerialId(16) val buId: Int = 0
@ProtoId(1) val groupCode: Long = 0L,
@ProtoId(2) val srcUin: Long = 0L,
@ProtoId(3) val fileId: Long = 0L,
@ProtoId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val fileSize: Long = 0L,
@ProtoId(6) val fileName: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(7) val srcTerm: Int = 0,
@ProtoId(8) val platformType: Int = 0,
@ProtoId(9) val buType: Int = 0,
@ProtoId(10) val buildVer: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(11) val innerIp: Int = 0,
@ProtoId(12) val voiceLength: Int = 0,
@ProtoId(13) val boolNewUpChan: Boolean = false,
@ProtoId(14) val codec: Int = 0,
@ProtoId(15) val voiceType: Int = 0,
@ProtoId(16) val buId: Int = 0
) : ProtoBuf
@Serializable
class TryUpPttRsp(
@SerialId(1) val fileId: Long = 0L,
@SerialId(2) val result: Int = 0,
@SerialId(3) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val boolFileExit: Boolean = false,
@SerialId(5) val uint32UpIp: List<Int>? = null,
@SerialId(6) val uint32UpPort: List<Int>? = null,
@SerialId(7) val upUkey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val fileid: Long = 0L,
@SerialId(9) val upOffset: Long = 0L,
@SerialId(10) val blockSize: Long = 0L,
@SerialId(11) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val channelType: Int = 0,
@SerialId(26) val msgUpIp6: List<IPv6Info>? = null,
@SerialId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val fileId: Long = 0L,
@ProtoId(2) val result: Int = 0,
@ProtoId(3) val failMsg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val boolFileExit: Boolean = false,
@ProtoId(5) val uint32UpIp: List<Int>? = null,
@ProtoId(6) val uint32UpPort: List<Int>? = null,
@ProtoId(7) val upUkey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(8) val fileid: Long = 0L,
@ProtoId(9) val upOffset: Long = 0L,
@ProtoId(10) val blockSize: Long = 0L,
@ProtoId(11) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(12) val channelType: Int = 0,
@ProtoId(26) val msgUpIp6: List<IPv6Info>? = null,
@ProtoId(27) val clientIp6: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
}

View File

@ -11,8 +11,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import kotlinx.serialization.protobuf.ProtoNumberType
import kotlinx.serialization.protobuf.ProtoType
import net.mamoe.mirai.qqandroid.io.ProtoBuf
@ -21,50 +21,50 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
class GroupOpenSysMsg : ProtoBuf {
@Serializable
class LightApp(
@SerialId(1) val app: String = "",
@SerialId(2) val view: String = "",
@SerialId(3) val desc: String = "",
@SerialId(4) val prompt: String = "",
@SerialId(5) val ver: String = "",
@SerialId(6) val meta: String = "",
@SerialId(7) val config: String = "",
@SerialId(8) val source: Source? = null
@ProtoId(1) val app: String = "",
@ProtoId(2) val view: String = "",
@ProtoId(3) val desc: String = "",
@ProtoId(4) val prompt: String = "",
@ProtoId(5) val ver: String = "",
@ProtoId(6) val meta: String = "",
@ProtoId(7) val config: String = "",
@ProtoId(8) val source: Source? = null
) : ProtoBuf
@Serializable
class RichMsg(
@SerialId(1) val title: String = "",
@SerialId(2) val desc: String = "",
@SerialId(3) val brief: String = "",
@SerialId(4) val cover: String = "",
@SerialId(5) val url: String = "",
@SerialId(6) val source: Source? = null
@ProtoId(1) val title: String = "",
@ProtoId(2) val desc: String = "",
@ProtoId(3) val brief: String = "",
@ProtoId(4) val cover: String = "",
@ProtoId(5) val url: String = "",
@ProtoId(6) val source: Source? = null
) : ProtoBuf
@Serializable
class Sender(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val nick: String = "",
@SerialId(3) val avatar: String = "",
@SerialId(4) val url: String = ""
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val nick: String = "",
@ProtoId(3) val avatar: String = "",
@ProtoId(4) val url: String = ""
) : ProtoBuf
@Serializable
class Source(
@SerialId(1) val name: String = "",
@SerialId(2) val icon: String = "",
@SerialId(3) val url: String = ""
@ProtoId(1) val name: String = "",
@ProtoId(2) val icon: String = "",
@ProtoId(3) val url: String = ""
) : ProtoBuf
@Serializable
class SysMsgBody(
@SerialId(1) val groupId: Long = 0L,
@SerialId(2) val appid: Long = 0L,
@SerialId(3) val sender: Sender? = null,
@SerialId(4) val msgType: Int = 0,
@SerialId(5) val content: String = "",
@SerialId(6) val richMsg: RichMsg? = null,
@SerialId(7) val lightApp: LightApp? = null
@ProtoId(1) val groupId: Long = 0L,
@ProtoId(2) val appid: Long = 0L,
@ProtoId(3) val sender: Sender? = null,
@ProtoId(4) val msgType: Int = 0,
@ProtoId(5) val content: String = "",
@ProtoId(6) val richMsg: RichMsg? = null,
@ProtoId(7) val lightApp: LightApp? = null
) : ProtoBuf
}
@ -72,337 +72,337 @@ class GroupOpenSysMsg : ProtoBuf {
class TroopTips0x857 : ProtoBuf {
@Serializable
class AIOGrayTipsInfo(
@SerialId(1) val optUint32ShowLastest: Int = 0,
@SerialId(2) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val optUint32Remind: Int = 0,
@SerialId(4) val optBytesBrief: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val receiverUin: Long = 0L,
@SerialId(6) val reliaoAdminOpt: Int = 0,
@SerialId(7) val robotGroupOpt: Int = 0
@ProtoId(1) val optUint32ShowLastest: Int = 0,
@ProtoId(2) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val optUint32Remind: Int = 0,
@ProtoId(4) val optBytesBrief: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val receiverUin: Long = 0L,
@ProtoId(6) val reliaoAdminOpt: Int = 0,
@ProtoId(7) val robotGroupOpt: Int = 0
) : ProtoBuf
@Serializable
class AIOTopTipsInfo(
@SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val optUint32Icon: Int = 0,
@SerialId(3) val optEnumAction: Int /* enum */ = 1,
@SerialId(4) val optBytesUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val optBytesData: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val optBytesDataI: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val optBytesDataA: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val optBytesDataP: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val optUint32Icon: Int = 0,
@ProtoId(3) val optEnumAction: Int /* enum */ = 1,
@ProtoId(4) val optBytesUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val optBytesData: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val optBytesDataI: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(7) val optBytesDataA: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(8) val optBytesDataP: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class FloatedTipsInfo(
@SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class GeneralGrayTipInfo(
@SerialId(1) val busiType: Long = 0L,
@SerialId(2) val busiId: Long = 0L,
@SerialId(3) val ctrlFlag: Int = 0,
@SerialId(4) val c2cType: Int = 0,
@SerialId(5) val serviceType: Int = 0,
@SerialId(6) val templId: Long = 0L,
@SerialId(7) val msgTemplParam: List<TemplParam>? = null,
@SerialId(8) val content: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val tipsSeqId: Long = 0L,
@SerialId(100) val pbReserv: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val busiType: Long = 0L,
@ProtoId(2) val busiId: Long = 0L,
@ProtoId(3) val ctrlFlag: Int = 0,
@ProtoId(4) val c2cType: Int = 0,
@ProtoId(5) val serviceType: Int = 0,
@ProtoId(6) val templId: Long = 0L,
@ProtoId(7) val msgTemplParam: List<TemplParam>? = null,
@ProtoId(8) val content: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(10) val tipsSeqId: Long = 0L,
@ProtoId(100) val pbReserv: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class GoldMsgTipsElem(
@SerialId(1) val type: Int = 0,
@SerialId(2) val billno: String = "",
@SerialId(3) val result: Int = 0,
@SerialId(4) val amount: Int = 0,
@SerialId(5) val total: Int = 0,
@SerialId(6) val interval: Int = 0,
@SerialId(7) val finish: Int = 0,
@SerialId(8) val uin: List<Long>? = null,
@SerialId(9) val action: Int = 0
@ProtoId(1) val type: Int = 0,
@ProtoId(2) val billno: String = "",
@ProtoId(3) val result: Int = 0,
@ProtoId(4) val amount: Int = 0,
@ProtoId(5) val total: Int = 0,
@ProtoId(6) val interval: Int = 0,
@ProtoId(7) val finish: Int = 0,
@ProtoId(8) val uin: List<Long>? = null,
@ProtoId(9) val action: Int = 0
) : ProtoBuf
@Serializable
class GroupInfoChange(
@SerialId(1) val groupHonorSwitch: Int = 0
@ProtoId(1) val groupHonorSwitch: Int = 0
) : ProtoBuf
@Serializable
class GroupNotifyInfo(
@SerialId(1) val optUint32AutoPullFlag: Int = 0,
@SerialId(2) val optBytesFeedsId: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val optUint32AutoPullFlag: Int = 0,
@ProtoId(2) val optBytesFeedsId: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class InstCtrl(
@SerialId(1) val msgSendToInst: List<InstInfo>? = null,
@SerialId(2) val msgExcludeInst: List<InstInfo>? = null,
@SerialId(3) val msgFromInst: InstInfo? = null
@ProtoId(1) val msgSendToInst: List<InstInfo>? = null,
@ProtoId(2) val msgExcludeInst: List<InstInfo>? = null,
@ProtoId(3) val msgFromInst: InstInfo? = null
) : ProtoBuf
@Serializable
class InstInfo(
@SerialId(1) val apppid: Int = 0,
@SerialId(2) val instid: Int = 0,
@SerialId(3) val platform: Int = 0,
@SerialId(4) val openAppid: Int = 0,
@SerialId(5) val productid: Int = 0,
@SerialId(6) val ssoBid: Int = 0,
@SerialId(7) val guid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val verMin: Int = 0,
@SerialId(9) val verMax: Int = 0
@ProtoId(1) val apppid: Int = 0,
@ProtoId(2) val instid: Int = 0,
@ProtoId(3) val platform: Int = 0,
@ProtoId(4) val openAppid: Int = 0,
@ProtoId(5) val productid: Int = 0,
@ProtoId(6) val ssoBid: Int = 0,
@ProtoId(7) val guid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(8) val verMin: Int = 0,
@ProtoId(9) val verMax: Int = 0
) : ProtoBuf
@Serializable
class LbsShareChangePushInfo(
@SerialId(1) val msgType: Int = 0,
@SerialId(2) val msgInfo: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val versionCtrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val groupId: Long = 0L,
@SerialId(5) val operUin: Long = 0L,
@SerialId(6) val grayTips: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val msgSeq: Long = 0L,
@SerialId(8) val joinNums: Int = 0,
@SerialId(99) val pushType: Int = 0,
@SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val msgType: Int = 0,
@ProtoId(2) val msgInfo: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val versionCtrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val groupId: Long = 0L,
@ProtoId(5) val operUin: Long = 0L,
@ProtoId(6) val grayTips: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(7) val msgSeq: Long = 0L,
@ProtoId(8) val joinNums: Int = 0,
@ProtoId(99) val pushType: Int = 0,
@ProtoId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class LuckyBagNotify(
@SerialId(1) val msgTips: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val msgTips: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class MediaChangePushInfo(
@SerialId(1) val msgType: Int = 0,
@SerialId(2) val msgInfo: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val versionCtrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val groupId: Long = 0L,
@SerialId(5) val operUin: Long = 0L,
@SerialId(6) val grayTips: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val msgSeq: Long = 0L,
@SerialId(8) val joinNums: Int = 0,
@SerialId(9) val msgPerSetting: PersonalSetting? = null,
@SerialId(10) val playMode: Int = 0,
@SerialId(99) val mediaType: Int = 0,
@SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val msgType: Int = 0,
@ProtoId(2) val msgInfo: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val versionCtrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val groupId: Long = 0L,
@ProtoId(5) val operUin: Long = 0L,
@ProtoId(6) val grayTips: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(7) val msgSeq: Long = 0L,
@ProtoId(8) val joinNums: Int = 0,
@ProtoId(9) val msgPerSetting: PersonalSetting? = null,
@ProtoId(10) val playMode: Int = 0,
@ProtoId(99) val mediaType: Int = 0,
@ProtoId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf {
@Serializable
class PersonalSetting(
@SerialId(1) val themeId: Int = 0,
@SerialId(2) val playerId: Int = 0,
@SerialId(3) val fontId: Int = 0
@ProtoId(1) val themeId: Int = 0,
@ProtoId(2) val playerId: Int = 0,
@ProtoId(3) val fontId: Int = 0
) : ProtoBuf
}
@Serializable
class MessageBoxInfo(
@SerialId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val optBytesTitle: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val optBytesButton: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val optBytesContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val optBytesTitle: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val optBytesButton: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class MessageRecallReminder(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val recalledMsgList: List<MessageMeta> = listOf(),
@SerialId(4) val reminderContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val userdef: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val groupType: Int = 0,
@SerialId(7) val opType: Int = 0
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val recalledMsgList: List<MessageMeta> = listOf(),
@ProtoId(4) val reminderContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val userdef: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val groupType: Int = 0,
@ProtoId(7) val opType: Int = 0
) : ProtoBuf {
@Serializable
class MessageMeta(
@SerialId(1) val seq: Int = 0,
@SerialId(2) val time: Int = 0,
@SerialId(3) val msgRandom: Int = 0,
@SerialId(4) val msgType: Int = 0,
@SerialId(5) val msgFlag: Int = 0,
@SerialId(6) val authorUin: Long = 0L
@ProtoId(1) val seq: Int = 0,
@ProtoId(2) val time: Int = 0,
@ProtoId(3) val msgRandom: Int = 0,
@ProtoId(4) val msgType: Int = 0,
@ProtoId(5) val msgFlag: Int = 0,
@ProtoId(6) val authorUin: Long = 0L
) : ProtoBuf
}
@Serializable
class MiniAppNotify(
@SerialId(1) val msg: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val msg: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class NotifyMsgBody(
@SerialId(1) val optEnumType: Int /* enum */ = 1,
@SerialId(2) val optUint64MsgTime: Long = 0L,
@SerialId(3) val optUint64MsgExpires: Long = 0L,
@SerialId(4) val optUint64GroupCode: Long = 0L,
@SerialId(5) val optMsgGraytips: AIOGrayTipsInfo? = null,
@SerialId(6) val optMsgMessagebox: MessageBoxInfo? = null,
@SerialId(7) val optMsgFloatedtips: FloatedTipsInfo? = null,
@SerialId(8) val optMsgToptips: AIOTopTipsInfo? = null,
@SerialId(9) val optMsgRedtips: RedGrayTipsInfo? = null,
@SerialId(10) val optMsgGroupNotify: GroupNotifyInfo? = null,
@SerialId(11) val optMsgRecall: MessageRecallReminder? = null,
@SerialId(12) val optMsgThemeNotify: ThemeStateNotify? = null,
@SerialId(13) val serviceType: Int = 0,
@SerialId(14) val optMsgObjmsgUpdate: NotifyObjmsgUpdate? = null,
@SerialId(15) val optMsgWerewolfPush: WereWolfPush? = null,
@ProtoId(1) val optEnumType: Int /* enum */ = 1,
@ProtoId(2) val optUint64MsgTime: Long = 0L,
@ProtoId(3) val optUint64MsgExpires: Long = 0L,
@ProtoId(4) val optUint64GroupCode: Long = 0L,
@ProtoId(5) val optMsgGraytips: AIOGrayTipsInfo? = null,
@ProtoId(6) val optMsgMessagebox: MessageBoxInfo? = null,
@ProtoId(7) val optMsgFloatedtips: FloatedTipsInfo? = null,
@ProtoId(8) val optMsgToptips: AIOTopTipsInfo? = null,
@ProtoId(9) val optMsgRedtips: RedGrayTipsInfo? = null,
@ProtoId(10) val optMsgGroupNotify: GroupNotifyInfo? = null,
@ProtoId(11) val optMsgRecall: MessageRecallReminder? = null,
@ProtoId(12) val optMsgThemeNotify: ThemeStateNotify? = null,
@ProtoId(13) val serviceType: Int = 0,
@ProtoId(14) val optMsgObjmsgUpdate: NotifyObjmsgUpdate? = null,
@ProtoId(15) val optMsgWerewolfPush: WereWolfPush? = null,
// @SerialId(16) val optStcmGameState: ApolloGameStatus.STCMGameMessage? = null,
// @SerialId(17) val aplloMsgPush: ApolloPushMsgInfo.STPushMsgElem? = null,
@SerialId(18) val optMsgGoldtips: GoldMsgTipsElem? = null,
@SerialId(20) val optMsgMiniappNotify: MiniAppNotify? = null,
@SerialId(21) val optUint64SenderUin: Long = 0L,
@SerialId(22) val optMsgLuckybagNotify: LuckyBagNotify? = null,
@SerialId(23) val optMsgTroopformtipsPush: TroopFormGrayTipsInfo? = null,
@SerialId(24) val optMsgMediaPush: MediaChangePushInfo? = null,
@SerialId(26) val optGeneralGrayTip: GeneralGrayTipInfo? = null,
@SerialId(27) val optMsgVideoPush: VideoChangePushInfo? = null,
@SerialId(28) val optLbsShareChangePlusInfo: LbsShareChangePushInfo? = null,
@SerialId(29) val optMsgSingPush: SingChangePushInfo? = null,
@SerialId(30) val optMsgGroupInfoChange: GroupInfoChange? = null
@ProtoId(18) val optMsgGoldtips: GoldMsgTipsElem? = null,
@ProtoId(20) val optMsgMiniappNotify: MiniAppNotify? = null,
@ProtoId(21) val optUint64SenderUin: Long = 0L,
@ProtoId(22) val optMsgLuckybagNotify: LuckyBagNotify? = null,
@ProtoId(23) val optMsgTroopformtipsPush: TroopFormGrayTipsInfo? = null,
@ProtoId(24) val optMsgMediaPush: MediaChangePushInfo? = null,
@ProtoId(26) val optGeneralGrayTip: GeneralGrayTipInfo? = null,
@ProtoId(27) val optMsgVideoPush: VideoChangePushInfo? = null,
@ProtoId(28) val optLbsShareChangePlusInfo: LbsShareChangePushInfo? = null,
@ProtoId(29) val optMsgSingPush: SingChangePushInfo? = null,
@ProtoId(30) val optMsgGroupInfoChange: GroupInfoChange? = null
) : ProtoBuf
@Serializable
class NotifyObjmsgUpdate(
@SerialId(1) val objmsgId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val updateType: Int = 0,
@SerialId(3) val extMsg: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val objmsgId: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val updateType: Int = 0,
@ProtoId(3) val extMsg: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class RedGrayTipsInfo(
@SerialId(1) val optUint32ShowLastest: Int = 0,
@SerialId(2) val senderUin: Long = 0L,
@SerialId(3) val receiverUin: Long = 0L,
@SerialId(4) val senderRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val receiverRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val authkey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(7) val sint32Msgtype: Int = 0,
@SerialId(8) val luckyFlag: Int = 0,
@SerialId(9) val hideFlag: Int = 0,
@SerialId(10) val pcBody: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val icon: Int = 0,
@SerialId(12) val luckyUin: Long = 0L,
@SerialId(13) val time: Int = 0,
@SerialId(14) val random: Int = 0,
@SerialId(15) val broadcastRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(16) val idiom: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(17) val idiomSeq: Int = 0,
@SerialId(18) val idiomAlpha: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(19) val jumpurl: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val optUint32ShowLastest: Int = 0,
@ProtoId(2) val senderUin: Long = 0L,
@ProtoId(3) val receiverUin: Long = 0L,
@ProtoId(4) val senderRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val receiverRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val authkey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoType(ProtoNumberType.SIGNED) @ProtoId(7) val sint32Msgtype: Int = 0,
@ProtoId(8) val luckyFlag: Int = 0,
@ProtoId(9) val hideFlag: Int = 0,
@ProtoId(10) val pcBody: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(11) val icon: Int = 0,
@ProtoId(12) val luckyUin: Long = 0L,
@ProtoId(13) val time: Int = 0,
@ProtoId(14) val random: Int = 0,
@ProtoId(15) val broadcastRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(16) val idiom: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(17) val idiomSeq: Int = 0,
@ProtoId(18) val idiomAlpha: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(19) val jumpurl: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ReqBody(
@SerialId(1) val optUint64GroupCode: Long = 0L,
@SerialId(2) val uint64Memberuins: List<Long>? = null,
@SerialId(3) val optUint32Offline: Int = 0,
@SerialId(4) val msgInstCtrl: InstCtrl? = null,
@SerialId(5) val optBytesMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val optUint32BusiType: Int = 0
@ProtoId(1) val optUint64GroupCode: Long = 0L,
@ProtoId(2) val uint64Memberuins: List<Long>? = null,
@ProtoId(3) val optUint32Offline: Int = 0,
@ProtoId(4) val msgInstCtrl: InstCtrl? = null,
@ProtoId(5) val optBytesMsg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val optUint32BusiType: Int = 0
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1) val optUint64GroupCode: Long = 0L
@ProtoId(1) val optUint64GroupCode: Long = 0L
) : ProtoBuf
@Serializable
class SingChangePushInfo(
@SerialId(1) val seq: Long = 0L,
@SerialId(2) val actionType: Int = 0,
@SerialId(3) val groupId: Long = 0L,
@SerialId(4) val operUin: Long = 0L,
@SerialId(5) val grayTips: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val joinNums: Int = 0
@ProtoId(1) val seq: Long = 0L,
@ProtoId(2) val actionType: Int = 0,
@ProtoId(3) val groupId: Long = 0L,
@ProtoId(4) val operUin: Long = 0L,
@ProtoId(5) val grayTips: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val joinNums: Int = 0
) : ProtoBuf
@Serializable
class TemplParam(
@SerialId(1) val name: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val value: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val name: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val value: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ThemeStateNotify(
@SerialId(1) val state: Int = 0,
@SerialId(2) val feedsId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val themeName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val actionUin: Long = 0L,
@SerialId(5) val createUin: Long = 0L
@ProtoId(1) val state: Int = 0,
@ProtoId(2) val feedsId: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val themeName: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val actionUin: Long = 0L,
@ProtoId(5) val createUin: Long = 0L
) : ProtoBuf
@Serializable
class TroopFormGrayTipsInfo(
@SerialId(1) val writerUin: Long = 0L,
@SerialId(2) val creatorUin: Long = 0L,
@SerialId(3) val richContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val optBytesUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val creatorNick: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val writerUin: Long = 0L,
@ProtoId(2) val creatorUin: Long = 0L,
@ProtoId(3) val richContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val optBytesUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val creatorNick: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class VideoChangePushInfo(
@SerialId(1) val seq: Long = 0L,
@SerialId(2) val actionType: Int = 0,
@SerialId(3) val groupId: Long = 0L,
@SerialId(4) val operUin: Long = 0L,
@SerialId(5) val grayTips: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val joinNums: Int = 0,
@SerialId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val seq: Long = 0L,
@ProtoId(2) val actionType: Int = 0,
@ProtoId(3) val groupId: Long = 0L,
@ProtoId(4) val operUin: Long = 0L,
@ProtoId(5) val grayTips: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val joinNums: Int = 0,
@ProtoId(100) val extInfo: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class WereWolfPush(
@SerialId(1) val pushType: Int = 0,
@SerialId(2) val gameRoom: Long = 0L,
@SerialId(3) val enumGameState: Int = 0,
@SerialId(4) val gameRound: Int = 0,
@SerialId(5) val roles: List<Role>? = null,
@SerialId(6) val speaker: Long = 0L,
@SerialId(7) val judgeUin: Long = 0L,
@SerialId(8) val judgeWords: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val enumOperation: Int = 0,
@SerialId(10) val srcUser: Long = 0L,
@SerialId(11) val dstUser: Long = 0L,
@SerialId(12) val deadUsers: List<Long>? = null,
@SerialId(13) val gameResult: Int = 0,
@SerialId(14) val timeoutSec: Int = 0,
@SerialId(15) val killConfirmed: Int = 0,
@SerialId(16) val judgeNickname: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(17) val votedTieUsers: List<Long>? = null
@ProtoId(1) val pushType: Int = 0,
@ProtoId(2) val gameRoom: Long = 0L,
@ProtoId(3) val enumGameState: Int = 0,
@ProtoId(4) val gameRound: Int = 0,
@ProtoId(5) val roles: List<Role>? = null,
@ProtoId(6) val speaker: Long = 0L,
@ProtoId(7) val judgeUin: Long = 0L,
@ProtoId(8) val judgeWords: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(9) val enumOperation: Int = 0,
@ProtoId(10) val srcUser: Long = 0L,
@ProtoId(11) val dstUser: Long = 0L,
@ProtoId(12) val deadUsers: List<Long>? = null,
@ProtoId(13) val gameResult: Int = 0,
@ProtoId(14) val timeoutSec: Int = 0,
@ProtoId(15) val killConfirmed: Int = 0,
@ProtoId(16) val judgeNickname: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(17) val votedTieUsers: List<Long>? = null
) : ProtoBuf {
@Serializable
class GameRecord(
@SerialId(1) val total: Int = 0,
@SerialId(2) val win: Int = 0,
@SerialId(3) val lose: Int = 0,
@SerialId(4) val draw: Int = 0
@ProtoId(1) val total: Int = 0,
@ProtoId(2) val win: Int = 0,
@ProtoId(3) val lose: Int = 0,
@ProtoId(4) val draw: Int = 0
) : ProtoBuf
@Serializable
class Role(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val enumType: Int = 0,
@SerialId(3) val enumState: Int = 0,
@SerialId(4) val canSpeak: Int = 0,
@SerialId(5) val canListen: Int = 0,
@SerialId(6) val position: Int = 0,
@SerialId(7) val canVote: Int = 0,
@SerialId(8) val canVoted: Int = 0,
@SerialId(9) val alreadyChecked: Int = 0,
@SerialId(10) val alreadySaved: Int = 0,
@SerialId(11) val alreadyPoisoned: Int = 0,
@SerialId(12) val playerState: Int = 0,
@SerialId(13) val enumDeadOp: Int = 0,
@SerialId(14) val enumOperation: Int = 0,
@SerialId(15) val dstUser: Long = 0L,
@SerialId(16) val operationRound: Int = 0,
@SerialId(17) val msgGameRecord: GameRecord? = null,
@SerialId(18) val isWerewolf: Int = 0,
@SerialId(19) val defendedUser: Long = 0L,
@SerialId(20) val isSheriff: Int = 0
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val enumType: Int = 0,
@ProtoId(3) val enumState: Int = 0,
@ProtoId(4) val canSpeak: Int = 0,
@ProtoId(5) val canListen: Int = 0,
@ProtoId(6) val position: Int = 0,
@ProtoId(7) val canVote: Int = 0,
@ProtoId(8) val canVoted: Int = 0,
@ProtoId(9) val alreadyChecked: Int = 0,
@ProtoId(10) val alreadySaved: Int = 0,
@ProtoId(11) val alreadyPoisoned: Int = 0,
@ProtoId(12) val playerState: Int = 0,
@ProtoId(13) val enumDeadOp: Int = 0,
@ProtoId(14) val enumOperation: Int = 0,
@ProtoId(15) val dstUser: Long = 0L,
@ProtoId(16) val operationRound: Int = 0,
@ProtoId(17) val msgGameRecord: GameRecord? = null,
@ProtoId(18) val isWerewolf: Int = 0,
@ProtoId(19) val defendedUser: Long = 0L,
@ProtoId(20) val isSheriff: Int = 0
) : ProtoBuf
}
}

View File

@ -11,8 +11,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import kotlinx.serialization.protobuf.ProtoNumberType
import kotlinx.serialization.protobuf.ProtoType
import net.mamoe.mirai.qqandroid.io.ProtoBuf
@ -22,74 +22,74 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
class Oidb0x858 : ProtoBuf {
@Serializable
class GoldMsgTipsElem(
@SerialId(1) val type: Int = 0,
@SerialId(2) val billno: String = "",
@SerialId(3) val result: Int = 0,
@SerialId(4) val amount: Int = 0,
@SerialId(5) val total: Int = 0,
@SerialId(6) val interval: Int = 0,
@SerialId(7) val finish: Int = 0,
@SerialId(8) val uin: List<Long>? = null,
@SerialId(9) val action: Int = 0
@ProtoId(1) val type: Int = 0,
@ProtoId(2) val billno: String = "",
@ProtoId(3) val result: Int = 0,
@ProtoId(4) val amount: Int = 0,
@ProtoId(5) val total: Int = 0,
@ProtoId(6) val interval: Int = 0,
@ProtoId(7) val finish: Int = 0,
@ProtoId(8) val uin: List<Long>? = null,
@ProtoId(9) val action: Int = 0
) : ProtoBuf
@Serializable
class MessageRecallReminder(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val recalledMsgList: List<MessageMeta> = listOf(),
@SerialId(4) val reminderContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val userdef: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val recalledMsgList: List<MessageMeta> = listOf(),
@ProtoId(4) val reminderContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val userdef: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf {
@Serializable
class MessageMeta(
@SerialId(1) val seq: Int = 0,
@SerialId(2) val time: Int = 0,
@SerialId(3) val msgRandom: Int = 0
@ProtoId(1) val seq: Int = 0,
@ProtoId(2) val time: Int = 0,
@ProtoId(3) val msgRandom: Int = 0
) : ProtoBuf
}
@Serializable
class NotifyMsgBody(
@SerialId(1) val optEnumType: Int /* enum */ = 5,
@SerialId(2) val optUint64MsgTime: Long = 0L,
@SerialId(3) val optUint64MsgExpires: Long = 0L,
@SerialId(4) val optUint64ConfUin: Long = 0L,
@SerialId(5) val optMsgRedtips: RedGrayTipsInfo? = null,
@SerialId(6) val optMsgRecallReminder: MessageRecallReminder? = null,
@SerialId(7) val optMsgObjUpdate: NotifyObjmsgUpdate? = null,
@ProtoId(1) val optEnumType: Int /* enum */ = 5,
@ProtoId(2) val optUint64MsgTime: Long = 0L,
@ProtoId(3) val optUint64MsgExpires: Long = 0L,
@ProtoId(4) val optUint64ConfUin: Long = 0L,
@ProtoId(5) val optMsgRedtips: RedGrayTipsInfo? = null,
@ProtoId(6) val optMsgRecallReminder: MessageRecallReminder? = null,
@ProtoId(7) val optMsgObjUpdate: NotifyObjmsgUpdate? = null,
// @SerialId(8) val optStcmGameState: ApolloGameStatus.STCMGameMessage? = null,
// @SerialId(9) val aplloMsgPush: ApolloPushMsgInfo.STPushMsgElem? = null,
@SerialId(10) val optMsgGoldtips: GoldMsgTipsElem? = null
@ProtoId(10) val optMsgGoldtips: GoldMsgTipsElem? = null
) : ProtoBuf
@Serializable
class NotifyObjmsgUpdate(
@SerialId(1) val objmsgId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val updateType: Int = 0,
@SerialId(3) val extMsg: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val objmsgId: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val updateType: Int = 0,
@ProtoId(3) val extMsg: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class RedGrayTipsInfo(
@SerialId(1) val optUint32ShowLastest: Int = 0,
@SerialId(2) val senderUin: Long = 0L,
@SerialId(3) val receiverUin: Long = 0L,
@SerialId(4) val senderRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val receiverRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val authkey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(7) val sint32Msgtype: Int = 0,
@SerialId(8) val luckyFlag: Int = 0,
@SerialId(9) val hideFlag: Int = 0,
@SerialId(10) val pcBody: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val icon: Int = 0,
@SerialId(12) val luckyUin: Long = 0L,
@SerialId(13) val time: Int = 0,
@SerialId(14) val random: Int = 0,
@SerialId(15) val broadcastRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(16) val idiom: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(17) val idiomSeq: Int = 0,
@SerialId(18) val idiomAlpha: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(19) val jumpurl: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val optUint32ShowLastest: Int = 0,
@ProtoId(2) val senderUin: Long = 0L,
@ProtoId(3) val receiverUin: Long = 0L,
@ProtoId(4) val senderRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val receiverRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val authkey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoType(ProtoNumberType.SIGNED) @ProtoId(7) val sint32Msgtype: Int = 0,
@ProtoId(8) val luckyFlag: Int = 0,
@ProtoId(9) val hideFlag: Int = 0,
@ProtoId(10) val pcBody: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(11) val icon: Int = 0,
@ProtoId(12) val luckyUin: Long = 0L,
@ProtoId(13) val time: Int = 0,
@ProtoId(14) val random: Int = 0,
@ProtoId(15) val broadcastRichContent: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(16) val idiom: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(17) val idiomSeq: Int = 0,
@ProtoId(18) val idiomAlpha: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(19) val jumpurl: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
}

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@ -18,56 +18,56 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
class Common : ProtoBuf {
@Serializable
class BindInfo(
@SerialId(1) val friUin: Long = 0L,
@SerialId(2) val friNick: String = "",
@SerialId(3) val time: Long = 0L,
@SerialId(4) val bindStatus: Int = 0
@ProtoId(1) val friUin: Long = 0L,
@ProtoId(2) val friNick: String = "",
@ProtoId(3) val time: Long = 0L,
@ProtoId(4) val bindStatus: Int = 0
) : ProtoBuf
@Serializable
class MedalInfo(
@SerialId(1) val id: Int = 0,
@SerialId(2) val type: Int = 0,
@SerialId(4) val seq: Long = 0,
@SerialId(5) val name: String = "",
@SerialId(6) val newflag: Int = 0,
@SerialId(7) val time: Long = 0L,
@SerialId(8) val msgBindFri: Common.BindInfo? = null,
@SerialId(11) val desc: String = "",
@SerialId(31) val level: Int = 0,
@SerialId(36) val taskinfos: List<Common.MedalTaskInfo>? = null,
@SerialId(40) val point: Int = 0,
@SerialId(41) val pointLevel2: Int = 0,
@SerialId(42) val pointLevel3: Int = 0,
@SerialId(43) val seqLevel2: Long = 0,
@SerialId(44) val seqLevel3: Long = 0,
@SerialId(45) val timeLevel2: Long = 0L,
@SerialId(46) val timeLevel3: Long = 0L,
@SerialId(47) val descLevel2: String = "",
@SerialId(48) val descLevel3: String = "",
@SerialId(49) val endtime: Int = 0,
@SerialId(50) val detailUrl: String = "",
@SerialId(51) val detailUrl2: String = "",
@SerialId(52) val detailUrl3: String = "",
@SerialId(53) val taskDesc: String = "",
@SerialId(54) val taskDesc2: String = "",
@SerialId(55) val taskDesc3: String = "",
@SerialId(56) val levelCount: Int = 0,
@SerialId(57) val noProgress: Int = 0,
@SerialId(58) val resource: String = "",
@SerialId(59) val fromuinLevel: Int = 0,
@SerialId(60) val unread: Int = 0,
@SerialId(61) val unread2: Int = 0,
@SerialId(62) val unread3: Int = 0
@ProtoId(1) val id: Int = 0,
@ProtoId(2) val type: Int = 0,
@ProtoId(4) val seq: Long = 0,
@ProtoId(5) val name: String = "",
@ProtoId(6) val newflag: Int = 0,
@ProtoId(7) val time: Long = 0L,
@ProtoId(8) val msgBindFri: Common.BindInfo? = null,
@ProtoId(11) val desc: String = "",
@ProtoId(31) val level: Int = 0,
@ProtoId(36) val taskinfos: List<Common.MedalTaskInfo>? = null,
@ProtoId(40) val point: Int = 0,
@ProtoId(41) val pointLevel2: Int = 0,
@ProtoId(42) val pointLevel3: Int = 0,
@ProtoId(43) val seqLevel2: Long = 0,
@ProtoId(44) val seqLevel3: Long = 0,
@ProtoId(45) val timeLevel2: Long = 0L,
@ProtoId(46) val timeLevel3: Long = 0L,
@ProtoId(47) val descLevel2: String = "",
@ProtoId(48) val descLevel3: String = "",
@ProtoId(49) val endtime: Int = 0,
@ProtoId(50) val detailUrl: String = "",
@ProtoId(51) val detailUrl2: String = "",
@ProtoId(52) val detailUrl3: String = "",
@ProtoId(53) val taskDesc: String = "",
@ProtoId(54) val taskDesc2: String = "",
@ProtoId(55) val taskDesc3: String = "",
@ProtoId(56) val levelCount: Int = 0,
@ProtoId(57) val noProgress: Int = 0,
@ProtoId(58) val resource: String = "",
@ProtoId(59) val fromuinLevel: Int = 0,
@ProtoId(60) val unread: Int = 0,
@ProtoId(61) val unread2: Int = 0,
@ProtoId(62) val unread3: Int = 0
) : ProtoBuf
@Serializable
class MedalTaskInfo(
@SerialId(1) val taskid: Int = 0,
@SerialId(32) val int32TaskValue: Int = 0,
@SerialId(33) val tarValue: Int = 0,
@SerialId(34) val tarValueLevel2: Int = 0,
@SerialId(35) val tarValueLevel3: Int = 0
@ProtoId(1) val taskid: Int = 0,
@ProtoId(32) val int32TaskValue: Int = 0,
@ProtoId(33) val tarValue: Int = 0,
@ProtoId(34) val tarValueLevel2: Int = 0,
@ProtoId(35) val tarValueLevel3: Int = 0
) : ProtoBuf
}
@ -75,475 +75,475 @@ class Common : ProtoBuf {
class AppointDefine : ProtoBuf {
@Serializable
class ADFeedContent(
@SerialId(1) val msgUserInfo: AppointDefine.UserInfo? = null,
@SerialId(2) val strPicUrl: List<String> = listOf(),
@SerialId(3) val msgText: AppointDefine.RichText? = null,
@SerialId(4) val attendInfo: String = "",
@SerialId(5) val actionUrl: String = "",
@SerialId(6) val publishTime: Int = 0,
@SerialId(7) val msgHotTopicList: AppointDefine.HotTopicList? = null,
@SerialId(8) val moreUrl: String = "",
@SerialId(9) val recordDuration: String = ""
@ProtoId(1) val msgUserInfo: AppointDefine.UserInfo? = null,
@ProtoId(2) val strPicUrl: List<String> = listOf(),
@ProtoId(3) val msgText: AppointDefine.RichText? = null,
@ProtoId(4) val attendInfo: String = "",
@ProtoId(5) val actionUrl: String = "",
@ProtoId(6) val publishTime: Int = 0,
@ProtoId(7) val msgHotTopicList: AppointDefine.HotTopicList? = null,
@ProtoId(8) val moreUrl: String = "",
@ProtoId(9) val recordDuration: String = ""
) : ProtoBuf
@Serializable
class RichText(
@SerialId(1) val msgElems: List<AppointDefine.Elem>? = null
@ProtoId(1) val msgElems: List<AppointDefine.Elem>? = null
) : ProtoBuf
@Serializable
class RankEvent(
@SerialId(1) val listtype: Int = 0,
@SerialId(2) val notifytype: Int = 0,
@SerialId(3) val eventtime: Int = 0,
@SerialId(4) val seq: Int = 0,
@SerialId(5) val notifyTips: String = ""
@ProtoId(1) val listtype: Int = 0,
@ProtoId(2) val notifytype: Int = 0,
@ProtoId(3) val eventtime: Int = 0,
@ProtoId(4) val seq: Int = 0,
@ProtoId(5) val notifyTips: String = ""
) : ProtoBuf
@Serializable
class Wifi(
@SerialId(1) val mac: Long = 0L,
@SerialId(2) val int32Rssi: Int = 0
@ProtoId(1) val mac: Long = 0L,
@ProtoId(2) val int32Rssi: Int = 0
) : ProtoBuf
@Serializable
class InterestItem(
@SerialId(1) val tagId: Long = 0L,
@SerialId(2) val tagName: String = "",
@SerialId(3) val tagIconUrl: String = "",
@SerialId(4) val tagHref: String = "",
@SerialId(5) val tagBackColor: String = "",
@SerialId(6) val tagFontColor: String = "",
@SerialId(7) val tagVid: String = "",
@SerialId(8) val tagType: Int = 0,
@SerialId(9) val addTime: Int = 0,
@SerialId(10) val tagCategory: String = "",
@SerialId(11) val tagOtherUrl: String = "",
@SerialId(12) val bid: Int = 0
@ProtoId(1) val tagId: Long = 0L,
@ProtoId(2) val tagName: String = "",
@ProtoId(3) val tagIconUrl: String = "",
@ProtoId(4) val tagHref: String = "",
@ProtoId(5) val tagBackColor: String = "",
@ProtoId(6) val tagFontColor: String = "",
@ProtoId(7) val tagVid: String = "",
@ProtoId(8) val tagType: Int = 0,
@ProtoId(9) val addTime: Int = 0,
@ProtoId(10) val tagCategory: String = "",
@ProtoId(11) val tagOtherUrl: String = "",
@ProtoId(12) val bid: Int = 0
) : ProtoBuf
@Serializable
class ShopID(
@SerialId(1) val shopid: String = "",
@SerialId(2) val sp: Int = 0
@ProtoId(1) val shopid: String = "",
@ProtoId(2) val sp: Int = 0
) : ProtoBuf
@Serializable
class FeedComment(
@SerialId(1) val commentId: String = "",
@SerialId(2) val feedId: String = "",
@SerialId(3) val msgPublisherInfo: AppointDefine.StrangerInfo? = null,
@SerialId(4) val time: Int = 0,
@SerialId(6) val msgReplyInfo: AppointDefine.ReplyInfo? = null,
@SerialId(7) val flag: Int = 0,
@SerialId(8) val msgContent: AppointDefine.RichText? = null,
@SerialId(9) val hot: Int = 0
@ProtoId(1) val commentId: String = "",
@ProtoId(2) val feedId: String = "",
@ProtoId(3) val msgPublisherInfo: AppointDefine.StrangerInfo? = null,
@ProtoId(4) val time: Int = 0,
@ProtoId(6) val msgReplyInfo: AppointDefine.ReplyInfo? = null,
@ProtoId(7) val flag: Int = 0,
@ProtoId(8) val msgContent: AppointDefine.RichText? = null,
@ProtoId(9) val hot: Int = 0
) : ProtoBuf
@Serializable
class ADFeed(
@SerialId(1) val taskId: Int = 0,
@SerialId(2) val style: Int = 0,
@SerialId(3) val content: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val taskId: Int = 0,
@ProtoId(2) val style: Int = 0,
@ProtoId(3) val content: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class Cell(
@SerialId(1) val int32Mcc: Int = -1,
@SerialId(2) val int32Mnc: Int = -1,
@SerialId(3) val int32Lac: Int = -1,
@SerialId(4) val int32Cellid: Int = -1,
@SerialId(5) val int32Rssi: Int = 0
@ProtoId(1) val int32Mcc: Int = -1,
@ProtoId(2) val int32Mnc: Int = -1,
@ProtoId(3) val int32Lac: Int = -1,
@ProtoId(4) val int32Cellid: Int = -1,
@ProtoId(5) val int32Rssi: Int = 0
) : ProtoBuf
@Serializable
class RecentVistorEvent(
@SerialId(1) val eventtype: Int = 0,
@SerialId(2) val eventTinyid: Long = 0L,
@SerialId(3) val unreadCount: Int = 0
@ProtoId(1) val eventtype: Int = 0,
@ProtoId(2) val eventTinyid: Long = 0L,
@ProtoId(3) val unreadCount: Int = 0
) : ProtoBuf
@Serializable
class OrganizerInfo(
@SerialId(1) val hostName: String = "",
@SerialId(2) val hostUrl: String = "",
@SerialId(3) val hostCover: String = ""
@ProtoId(1) val hostName: String = "",
@ProtoId(2) val hostUrl: String = "",
@ProtoId(3) val hostCover: String = ""
) : ProtoBuf
@Serializable
class InterestTag(
@SerialId(1) val tagType: Int = 0,
@SerialId(2) val msgTagList: List<AppointDefine.InterestItem>? = null
@ProtoId(1) val tagType: Int = 0,
@ProtoId(2) val msgTagList: List<AppointDefine.InterestItem>? = null
) : ProtoBuf
@Serializable
class AppointInfoEx(
@SerialId(1) val feedsPicUrl: String = "",
@SerialId(2) val feedsUrl: String = "",
@SerialId(3) val detailTitle: String = "",
@SerialId(4) val detailDescribe: String = "",
@SerialId(5) val showPublisher: Int = 0,
@SerialId(6) val detailPicUrl: String = "",
@SerialId(7) val detailUrl: String = "",
@SerialId(8) val showAttend: Int = 0
@ProtoId(1) val feedsPicUrl: String = "",
@ProtoId(2) val feedsUrl: String = "",
@ProtoId(3) val detailTitle: String = "",
@ProtoId(4) val detailDescribe: String = "",
@ProtoId(5) val showPublisher: Int = 0,
@ProtoId(6) val detailPicUrl: String = "",
@ProtoId(7) val detailUrl: String = "",
@ProtoId(8) val showAttend: Int = 0
) : ProtoBuf
@Serializable
class DateComment(
@SerialId(1) val commentId: String = "",
@SerialId(2) val msgAppointId: AppointDefine.AppointID? = null,
@SerialId(3) val msgPublisherInfo: AppointDefine.StrangerInfo? = null,
@SerialId(4) val time: Int = 0,
@SerialId(6) val msgReplyInfo: AppointDefine.ReplyInfo? = null,
@SerialId(7) val flag: Int = 0,
@SerialId(8) val msgContent: AppointDefine.RichText? = null
@ProtoId(1) val commentId: String = "",
@ProtoId(2) val msgAppointId: AppointDefine.AppointID? = null,
@ProtoId(3) val msgPublisherInfo: AppointDefine.StrangerInfo? = null,
@ProtoId(4) val time: Int = 0,
@ProtoId(6) val msgReplyInfo: AppointDefine.ReplyInfo? = null,
@ProtoId(7) val flag: Int = 0,
@ProtoId(8) val msgContent: AppointDefine.RichText? = null
) : ProtoBuf
@Serializable
class AppointContent(
@SerialId(1) val appointSubject: Int = 0,
@SerialId(2) val payType: Int = 0,
@SerialId(3) val appointDate: Int = 0,
@SerialId(4) val appointGender: Int = 0,
@SerialId(5) val appointIntroduce: String = "",
@SerialId(6) val msgAppointAddress: AppointDefine.AddressInfo? = null,
@SerialId(7) val msgTravelInfo: AppointDefine.TravelInfo? = null
@ProtoId(1) val appointSubject: Int = 0,
@ProtoId(2) val payType: Int = 0,
@ProtoId(3) val appointDate: Int = 0,
@ProtoId(4) val appointGender: Int = 0,
@ProtoId(5) val appointIntroduce: String = "",
@ProtoId(6) val msgAppointAddress: AppointDefine.AddressInfo? = null,
@ProtoId(7) val msgTravelInfo: AppointDefine.TravelInfo? = null
) : ProtoBuf
@Serializable
class FeedInfo(
@SerialId(1) val feedType: Long = 0L,
@SerialId(2) val feedId: String = "",
@SerialId(3) val msgFeedContent: AppointDefine.FeedContent? = null,
@SerialId(4) val msgTopicInfo: AppointDefine.NearbyTopic? = null,
@SerialId(5) val publishTime: Long = 0,
@SerialId(6) val praiseCount: Int = 0,
@SerialId(7) val praiseFlag: Int = 0,
@SerialId(8) val msgPraiseUser: List<AppointDefine.StrangerInfo>? = null,
@SerialId(9) val commentCount: Int = 0,
@SerialId(10) val msgCommentList: List<AppointDefine.FeedComment>? = null,
@SerialId(11) val commentRetAll: Int = 0,
@SerialId(12) val hotFlag: Int = 0,
@SerialId(13) val svrReserved: Long = 0L,
@SerialId(14) val msgHotEntry: AppointDefine.HotEntry? = null
@ProtoId(1) val feedType: Long = 0L,
@ProtoId(2) val feedId: String = "",
@ProtoId(3) val msgFeedContent: AppointDefine.FeedContent? = null,
@ProtoId(4) val msgTopicInfo: AppointDefine.NearbyTopic? = null,
@ProtoId(5) val publishTime: Long = 0,
@ProtoId(6) val praiseCount: Int = 0,
@ProtoId(7) val praiseFlag: Int = 0,
@ProtoId(8) val msgPraiseUser: List<AppointDefine.StrangerInfo>? = null,
@ProtoId(9) val commentCount: Int = 0,
@ProtoId(10) val msgCommentList: List<AppointDefine.FeedComment>? = null,
@ProtoId(11) val commentRetAll: Int = 0,
@ProtoId(12) val hotFlag: Int = 0,
@ProtoId(13) val svrReserved: Long = 0L,
@ProtoId(14) val msgHotEntry: AppointDefine.HotEntry? = null
) : ProtoBuf
@Serializable
class HotTopicList(
@SerialId(1) val topicList: List<AppointDefine.HotTopic>? = null
@ProtoId(1) val topicList: List<AppointDefine.HotTopic>? = null
) : ProtoBuf
@Serializable
class FeedContent(
@SerialId(1) val strPicUrl: List<String> = listOf(),
@SerialId(2) val msgText: AppointDefine.RichText? = null,
@SerialId(3) val hrefUrl: String = "",
@SerialId(5) val groupName: String = "",
@SerialId(6) val groupBulletin: String = "",
@SerialId(7) val feedType: Int = 0,
@SerialId(8) val poiId: String = "",
@SerialId(9) val poiTitle: String = "",
@SerialId(20) val effectiveTime: Int = 0,
@SerialId(21) val expiationTime: Int = 0,
@SerialId(22) val msgLocale: AppointDefine.LocaleInfo? = null,
@SerialId(23) val feedsIndex: Int = 0,
@SerialId(24) val msgAd: AppointDefine.ADFeed? = null,
@SerialId(25) val privateData: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val strPicUrl: List<String> = listOf(),
@ProtoId(2) val msgText: AppointDefine.RichText? = null,
@ProtoId(3) val hrefUrl: String = "",
@ProtoId(5) val groupName: String = "",
@ProtoId(6) val groupBulletin: String = "",
@ProtoId(7) val feedType: Int = 0,
@ProtoId(8) val poiId: String = "",
@ProtoId(9) val poiTitle: String = "",
@ProtoId(20) val effectiveTime: Int = 0,
@ProtoId(21) val expiationTime: Int = 0,
@ProtoId(22) val msgLocale: AppointDefine.LocaleInfo? = null,
@ProtoId(23) val feedsIndex: Int = 0,
@ProtoId(24) val msgAd: AppointDefine.ADFeed? = null,
@ProtoId(25) val privateData: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class TravelInfo(
@SerialId(1) val msgDepartLocale: AppointDefine.LocaleInfo? = null,
@SerialId(2) val msgDestination: AppointDefine.LocaleInfo? = null,
@SerialId(3) val vehicle: Int = 0,
@SerialId(4) val partnerCount: Int = 0,
@SerialId(5) val placePicUrl: String = "",
@SerialId(6) val placeUrl: String = ""
@ProtoId(1) val msgDepartLocale: AppointDefine.LocaleInfo? = null,
@ProtoId(2) val msgDestination: AppointDefine.LocaleInfo? = null,
@ProtoId(3) val vehicle: Int = 0,
@ProtoId(4) val partnerCount: Int = 0,
@ProtoId(5) val placePicUrl: String = "",
@ProtoId(6) val placeUrl: String = ""
) : ProtoBuf
@Serializable
class RecentFreshFeed(
@SerialId(1) val freshFeedInfo: List<AppointDefine.FreshFeedInfo>? = null,
@SerialId(2) val uid: Long = 0L
@ProtoId(1) val freshFeedInfo: List<AppointDefine.FreshFeedInfo>? = null,
@ProtoId(2) val uid: Long = 0L
) : ProtoBuf
@Serializable
class GPS(
@SerialId(1) val int32Lat: Int = 900000000,
@SerialId(2) val int32Lon: Int = 900000000,
@SerialId(3) val int32Alt: Int = -10000000,
@SerialId(4) val int32Type: Int = 0
@ProtoId(1) val int32Lat: Int = 900000000,
@ProtoId(2) val int32Lon: Int = 900000000,
@ProtoId(3) val int32Alt: Int = -10000000,
@ProtoId(4) val int32Type: Int = 0
) : ProtoBuf
@Serializable
class AppointID(
@SerialId(1) val requestId: String = ""
@ProtoId(1) val requestId: String = ""
) : ProtoBuf
@Serializable
class LocaleInfo(
@SerialId(1) val name: String = "",
@SerialId(2) val country: String = "",
@SerialId(3) val province: String = "",
@SerialId(4) val city: String = "",
@SerialId(5) val region: String = "",
@SerialId(6) val poi: String = "",
@SerialId(7) val msgGps: AppointDefine.GPS? = null,
@SerialId(8) val address: String = ""
@ProtoId(1) val name: String = "",
@ProtoId(2) val country: String = "",
@ProtoId(3) val province: String = "",
@ProtoId(4) val city: String = "",
@ProtoId(5) val region: String = "",
@ProtoId(6) val poi: String = "",
@ProtoId(7) val msgGps: AppointDefine.GPS? = null,
@ProtoId(8) val address: String = ""
) : ProtoBuf
@Serializable
class LBSInfo(
@SerialId(1) val msgGps: AppointDefine.GPS? = null,
@SerialId(2) val msgWifis: List<AppointDefine.Wifi>? = null,
@SerialId(3) val msgCells: List<AppointDefine.Cell>? = null
@ProtoId(1) val msgGps: AppointDefine.GPS? = null,
@ProtoId(2) val msgWifis: List<AppointDefine.Wifi>? = null,
@ProtoId(3) val msgCells: List<AppointDefine.Cell>? = null
) : ProtoBuf
@Serializable
class FeedEvent(
@SerialId(1) val eventId: Long = 0L,
@SerialId(2) val time: Int = 0,
@SerialId(3) val eventtype: Int = 0,
@SerialId(4) val msgUserInfo: AppointDefine.StrangerInfo? = null,
@SerialId(5) val msgFeedInfo: AppointDefine.FeedInfo? = null,
@SerialId(6) val eventTips: String = "",
@SerialId(7) val msgComment: AppointDefine.FeedComment? = null,
@SerialId(8) val cancelEventId: Long = 0L
@ProtoId(1) val eventId: Long = 0L,
@ProtoId(2) val time: Int = 0,
@ProtoId(3) val eventtype: Int = 0,
@ProtoId(4) val msgUserInfo: AppointDefine.StrangerInfo? = null,
@ProtoId(5) val msgFeedInfo: AppointDefine.FeedInfo? = null,
@ProtoId(6) val eventTips: String = "",
@ProtoId(7) val msgComment: AppointDefine.FeedComment? = null,
@ProtoId(8) val cancelEventId: Long = 0L
) : ProtoBuf
@Serializable
class FeedsCookie(
@SerialId(1) val strList: List<String> = listOf(),
@SerialId(2) val pose: Int = 0,
@SerialId(3) val cookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val uint64Topics: List<Long>? = null
@ProtoId(1) val strList: List<String> = listOf(),
@ProtoId(2) val pose: Int = 0,
@ProtoId(3) val cookie: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val uint64Topics: List<Long>? = null
) : ProtoBuf
@Serializable
class NearbyTopic(
@SerialId(1) val topicId: Long = 0L,
@SerialId(2) val topic: String = "",
@SerialId(3) val foreword: String = "",
@SerialId(4) val createTime: Int = 0,
@SerialId(5) val updateTime: Int = 0,
@SerialId(6) val hotFlag: Int = 0,
@SerialId(7) val buttonStyle: Int = 0,
@SerialId(8) val buttonSrc: String = "",
@SerialId(9) val backgroundSrc: String = "",
@SerialId(10) val attendeeInfo: String = "",
@SerialId(11) val index: Int = 0,
@SerialId(12) val publishScope: Int = 0,
@SerialId(13) val effectiveTime: Int = 0,
@SerialId(14) val expiationTime: Int = 0,
@SerialId(15) val pushedUsrCount: Int = 0,
@SerialId(16) val timerangeLeft: Int = 0,
@SerialId(17) val timerangeRight: Int = 0,
@SerialId(18) val area: String = ""
@ProtoId(1) val topicId: Long = 0L,
@ProtoId(2) val topic: String = "",
@ProtoId(3) val foreword: String = "",
@ProtoId(4) val createTime: Int = 0,
@ProtoId(5) val updateTime: Int = 0,
@ProtoId(6) val hotFlag: Int = 0,
@ProtoId(7) val buttonStyle: Int = 0,
@ProtoId(8) val buttonSrc: String = "",
@ProtoId(9) val backgroundSrc: String = "",
@ProtoId(10) val attendeeInfo: String = "",
@ProtoId(11) val index: Int = 0,
@ProtoId(12) val publishScope: Int = 0,
@ProtoId(13) val effectiveTime: Int = 0,
@ProtoId(14) val expiationTime: Int = 0,
@ProtoId(15) val pushedUsrCount: Int = 0,
@ProtoId(16) val timerangeLeft: Int = 0,
@ProtoId(17) val timerangeRight: Int = 0,
@ProtoId(18) val area: String = ""
) : ProtoBuf
@Serializable
class NearbyEvent(
@SerialId(1) val eventtype: Int = 0,
@SerialId(2) val msgRankevent: AppointDefine.RankEvent? = null,
@SerialId(3) val eventUin: Long = 0L,
@SerialId(4) val eventTinyid: Long = 0L
@ProtoId(1) val eventtype: Int = 0,
@ProtoId(2) val msgRankevent: AppointDefine.RankEvent? = null,
@ProtoId(3) val eventUin: Long = 0L,
@ProtoId(4) val eventTinyid: Long = 0L
) : ProtoBuf
@Serializable
class Feed(
@SerialId(1) val msgUserInfo: AppointDefine.PublisherInfo? = null,
@SerialId(2) val msgFeedInfo: AppointDefine.FeedInfo? = null,
@SerialId(3) val ownerFlag: Int = 0
@ProtoId(1) val msgUserInfo: AppointDefine.PublisherInfo? = null,
@ProtoId(2) val msgFeedInfo: AppointDefine.FeedInfo? = null,
@ProtoId(3) val ownerFlag: Int = 0
) : ProtoBuf
@Serializable
class ActivityInfo(
@SerialId(2) val name: String = "",
@SerialId(3) val cover: String = "",
@SerialId(4) val url: String = "",
@SerialId(5) val startTime: Int = 0,
@SerialId(6) val endTime: Int = 0,
@SerialId(7) val locName: String = "",
@SerialId(8) val enroll: Long = 0L,
@SerialId(9) val createUin: Long = 0L,
@SerialId(10) val createTime: Int = 0,
@SerialId(11) val organizerInfo: AppointDefine.OrganizerInfo = OrganizerInfo(),
@SerialId(12) val flag: Long? = null
@ProtoId(2) val name: String = "",
@ProtoId(3) val cover: String = "",
@ProtoId(4) val url: String = "",
@ProtoId(5) val startTime: Int = 0,
@ProtoId(6) val endTime: Int = 0,
@ProtoId(7) val locName: String = "",
@ProtoId(8) val enroll: Long = 0L,
@ProtoId(9) val createUin: Long = 0L,
@ProtoId(10) val createTime: Int = 0,
@ProtoId(11) val organizerInfo: AppointDefine.OrganizerInfo = OrganizerInfo(),
@ProtoId(12) val flag: Long? = null
) : ProtoBuf
@Serializable
class HotEntry(
@SerialId(1) val openFlag: Int = 0,
@SerialId(2) val restTime: Int = 0,
@SerialId(3) val foreword: String = "",
@SerialId(4) val backgroundSrc: String = ""
@ProtoId(1) val openFlag: Int = 0,
@ProtoId(2) val restTime: Int = 0,
@ProtoId(3) val foreword: String = "",
@ProtoId(4) val backgroundSrc: String = ""
) : ProtoBuf
@Serializable
class UserFeed(
@SerialId(1) val msgUserInfo: AppointDefine.PublisherInfo? = null,
@SerialId(2) val msgFeedInfo: AppointDefine.FeedInfo? = null,
@SerialId(3) val ownerFlag: Int = 0,
@SerialId(4) val msgActivityInfo: AppointDefine.ActivityInfo? = null
@ProtoId(1) val msgUserInfo: AppointDefine.PublisherInfo? = null,
@ProtoId(2) val msgFeedInfo: AppointDefine.FeedInfo? = null,
@ProtoId(3) val ownerFlag: Int = 0,
@ProtoId(4) val msgActivityInfo: AppointDefine.ActivityInfo? = null
) : ProtoBuf
@Serializable
class Elem(
@SerialId(1) val content: String = "",
@SerialId(2) val msgFaceInfo: AppointDefine.Face? = null
@ProtoId(1) val content: String = "",
@ProtoId(2) val msgFaceInfo: AppointDefine.Face? = null
) : ProtoBuf
@Serializable
class HotFreshFeedList(
@SerialId(1) val msgFeeds: List<AppointDefine.HotUserFeed>? = null,
@SerialId(2) val updateTime: Int = 0
@ProtoId(1) val msgFeeds: List<AppointDefine.HotUserFeed>? = null,
@ProtoId(2) val updateTime: Int = 0
) : ProtoBuf
@Serializable
class RptInterestTag(
@SerialId(1) val interestTags: List<AppointDefine.InterestTag>? = null
@ProtoId(1) val interestTags: List<AppointDefine.InterestTag>? = null
) : ProtoBuf
@Serializable
class AddressInfo(
@SerialId(1) val companyZone: String = "",
@SerialId(2) val companyName: String = "",
@SerialId(3) val companyAddr: String = "",
@SerialId(4) val companyPicUrl: String = "",
@SerialId(5) val companyUrl: String = "",
@SerialId(6) val msgCompanyId: AppointDefine.ShopID? = null
@ProtoId(1) val companyZone: String = "",
@ProtoId(2) val companyName: String = "",
@ProtoId(3) val companyAddr: String = "",
@ProtoId(4) val companyPicUrl: String = "",
@ProtoId(5) val companyUrl: String = "",
@ProtoId(6) val msgCompanyId: AppointDefine.ShopID? = null
) : ProtoBuf
@Serializable
class PublisherInfo(
@SerialId(1) val tinyid: Long = 0L,
@SerialId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val age: Int = 0,
@SerialId(4) val gender: Int = 0,
@SerialId(5) val constellation: String = "",
@SerialId(6) val profession: Int = 0,
@SerialId(7) val distance: String = "",
@SerialId(8) val marriage: Int = 0,
@SerialId(9) val vipinfo: String = "",
@SerialId(10) val recommend: Int = 0,
@SerialId(11) val godflag: Int = 0,
@SerialId(12) val chatflag: Int = 0,
@SerialId(13) val chatupCount: Int = 0,
@SerialId(14) val charm: Int = 0,
@SerialId(15) val charmLevel: Int = 0,
@SerialId(16) val pubNumber: Int = 0,
@SerialId(17) val msgCommonLabel: AppointDefine.CommonLabel? = null,
@SerialId(18) val recentVistorTime: Int = 0,
@SerialId(19) val strangerDeclare: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(20) val friendUin: Long = 0L,
@SerialId(21) val historyFlag: Int = 0,
@SerialId(22) val followflag: Long = 0L
@ProtoId(1) val tinyid: Long = 0L,
@ProtoId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val age: Int = 0,
@ProtoId(4) val gender: Int = 0,
@ProtoId(5) val constellation: String = "",
@ProtoId(6) val profession: Int = 0,
@ProtoId(7) val distance: String = "",
@ProtoId(8) val marriage: Int = 0,
@ProtoId(9) val vipinfo: String = "",
@ProtoId(10) val recommend: Int = 0,
@ProtoId(11) val godflag: Int = 0,
@ProtoId(12) val chatflag: Int = 0,
@ProtoId(13) val chatupCount: Int = 0,
@ProtoId(14) val charm: Int = 0,
@ProtoId(15) val charmLevel: Int = 0,
@ProtoId(16) val pubNumber: Int = 0,
@ProtoId(17) val msgCommonLabel: AppointDefine.CommonLabel? = null,
@ProtoId(18) val recentVistorTime: Int = 0,
@ProtoId(19) val strangerDeclare: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(20) val friendUin: Long = 0L,
@ProtoId(21) val historyFlag: Int = 0,
@ProtoId(22) val followflag: Long = 0L
) : ProtoBuf
@Serializable
class HotUserFeed(
@SerialId(1) val feedId: String = "",
@SerialId(2) val praiseCount: Int = 0,
@SerialId(3) val publishUid: Long = 0L,
@SerialId(4) val publishTime: Int = 0
@ProtoId(1) val feedId: String = "",
@ProtoId(2) val praiseCount: Int = 0,
@ProtoId(3) val publishUid: Long = 0L,
@ProtoId(4) val publishTime: Int = 0
) : ProtoBuf
@Serializable
class FreshFeedInfo(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val time: Int = 0,
@SerialId(3) val feedId: String = "",
@SerialId(4) val feedType: Long = 0L
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val time: Int = 0,
@ProtoId(3) val feedId: String = "",
@ProtoId(4) val feedType: Long = 0L
) : ProtoBuf
@Serializable
class CommonLabel(
@SerialId(1) val lableId: Int = 0,
@SerialId(2) val lableMsgPre: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val lableMsgLast: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val interstName: List<ByteArray>? = null,
@SerialId(5) val interstType: List<Int>? = null
@ProtoId(1) val lableId: Int = 0,
@ProtoId(2) val lableMsgPre: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val lableMsgLast: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val interstName: List<ByteArray>? = null,
@ProtoId(5) val interstType: List<Int>? = null
) : ProtoBuf
@Serializable
class Face(
@SerialId(1) val index: Int = 0
@ProtoId(1) val index: Int = 0
) : ProtoBuf
@Serializable
class StrangerInfo(
@SerialId(1) val tinyid: Long = 0L,
@SerialId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val age: Int = 0,
@SerialId(4) val gender: Int = 0,
@SerialId(5) val dating: Int = 0,
@SerialId(6) val listIdx: Int = 0,
@SerialId(7) val constellation: String = "",
@SerialId(8) val profession: Int = 0,
@SerialId(9) val marriage: Int = 0,
@SerialId(10) val vipinfo: String = "",
@SerialId(11) val recommend: Int = 0,
@SerialId(12) val godflag: Int = 0,
@SerialId(13) val charm: Int = 0,
@SerialId(14) val charmLevel: Int = 0,
@SerialId(15) val uin: Long = 0L
@ProtoId(1) val tinyid: Long = 0L,
@ProtoId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val age: Int = 0,
@ProtoId(4) val gender: Int = 0,
@ProtoId(5) val dating: Int = 0,
@ProtoId(6) val listIdx: Int = 0,
@ProtoId(7) val constellation: String = "",
@ProtoId(8) val profession: Int = 0,
@ProtoId(9) val marriage: Int = 0,
@ProtoId(10) val vipinfo: String = "",
@ProtoId(11) val recommend: Int = 0,
@ProtoId(12) val godflag: Int = 0,
@ProtoId(13) val charm: Int = 0,
@ProtoId(14) val charmLevel: Int = 0,
@ProtoId(15) val uin: Long = 0L
) : ProtoBuf
@Serializable
class HotTopic(
@SerialId(1) val id: Long = 0L,
@SerialId(2) val title: String = "",
@SerialId(3) val topicType: Long = 0L,
@SerialId(4) val total: Long = 0L,
@SerialId(5) val times: Long = 0L,
@SerialId(6) val historyTimes: Long = 0L,
@SerialId(7) val bgUrl: String = "",
@SerialId(8) val url: String = "",
@SerialId(9) val extraInfo: String = ""
@ProtoId(1) val id: Long = 0L,
@ProtoId(2) val title: String = "",
@ProtoId(3) val topicType: Long = 0L,
@ProtoId(4) val total: Long = 0L,
@ProtoId(5) val times: Long = 0L,
@ProtoId(6) val historyTimes: Long = 0L,
@ProtoId(7) val bgUrl: String = "",
@ProtoId(8) val url: String = "",
@ProtoId(9) val extraInfo: String = ""
) : ProtoBuf
@Serializable
class DateEvent(
@SerialId(1) val eventId: Long = 0L,
@SerialId(2) val time: Int = 0,
@SerialId(3) val type: Int = 0,
@SerialId(4) val msgUserInfo: AppointDefine.StrangerInfo? = null,
@SerialId(5) val msgDateInfo: AppointDefine.AppointInfo? = null,
@SerialId(6) val attendIdx: Int = 0,
@SerialId(7) val eventTips: String = "",
@SerialId(8) val msgComment: AppointDefine.DateComment? = null,
@SerialId(9) val cancelEventId: Long = 0L
@ProtoId(1) val eventId: Long = 0L,
@ProtoId(2) val time: Int = 0,
@ProtoId(3) val type: Int = 0,
@ProtoId(4) val msgUserInfo: AppointDefine.StrangerInfo? = null,
@ProtoId(5) val msgDateInfo: AppointDefine.AppointInfo? = null,
@ProtoId(6) val attendIdx: Int = 0,
@ProtoId(7) val eventTips: String = "",
@ProtoId(8) val msgComment: AppointDefine.DateComment? = null,
@ProtoId(9) val cancelEventId: Long = 0L
) : ProtoBuf
@Serializable
class AppointInfo(
@SerialId(1) val msgAppointId: AppointDefine.AppointID? = null,
@SerialId(2) val msgAppointment: AppointDefine.AppointContent? = null,
@SerialId(3) val appointStatus: Int = 0,
@SerialId(4) val joinWording: String = "",
@SerialId(5) val viewWording: String = "",
@SerialId(6) val unreadCount: Int = 0,
@SerialId(7) val owner: Int = 0,
@SerialId(8) val join: Int = 0,
@SerialId(9) val view: Int = 0,
@SerialId(10) val commentWording: String = "",
@SerialId(11) val commentNum: Int = 0,
@SerialId(12) val attendStatus: Int = 0,
@SerialId(13) val msgAppointmentEx: AppointDefine.AppointInfoEx? = null
@ProtoId(1) val msgAppointId: AppointDefine.AppointID? = null,
@ProtoId(2) val msgAppointment: AppointDefine.AppointContent? = null,
@ProtoId(3) val appointStatus: Int = 0,
@ProtoId(4) val joinWording: String = "",
@ProtoId(5) val viewWording: String = "",
@ProtoId(6) val unreadCount: Int = 0,
@ProtoId(7) val owner: Int = 0,
@ProtoId(8) val join: Int = 0,
@ProtoId(9) val view: Int = 0,
@ProtoId(10) val commentWording: String = "",
@ProtoId(11) val commentNum: Int = 0,
@ProtoId(12) val attendStatus: Int = 0,
@ProtoId(13) val msgAppointmentEx: AppointDefine.AppointInfoEx? = null
) : ProtoBuf
@Serializable
class UserInfo(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val age: Int = 0,
@SerialId(4) val gender: Int = 0,
@SerialId(5) val avatar: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val age: Int = 0,
@ProtoId(4) val gender: Int = 0,
@ProtoId(5) val avatar: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ReplyInfo(
@SerialId(1) val commentId: String = "",
@SerialId(2) val msgStrangerInfo: AppointDefine.StrangerInfo? = null
@ProtoId(1) val commentId: String = "",
@ProtoId(2) val msgStrangerInfo: AppointDefine.StrangerInfo? = null
) : ProtoBuf
}

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@ -18,40 +18,40 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
internal class Vec0xd50 : ProtoBuf {
@Serializable
internal class ExtSnsFrdData(
@SerialId(1) val frdUin: Long = 0L,
@SerialId(91001) val musicSwitch: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(101001) val mutualmarkAlienation: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(141001) val mutualmarkScore: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(151001) val ksingSwitch: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(181001) val lbsShare: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val frdUin: Long = 0L,
@ProtoId(91001) val musicSwitch: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(101001) val mutualmarkAlienation: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(141001) val mutualmarkScore: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(151001) val ksingSwitch: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(181001) val lbsShare: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
internal class RspBody(
@SerialId(1) val msgUpdateData: List<Vec0xd50.ExtSnsFrdData>? = null,
@SerialId(11) val over: Int = 0,
@SerialId(12) val nextStart: Int = 0,
@SerialId(13) val uint64UnfinishedUins: List<Long>? = null
@ProtoId(1) val msgUpdateData: List<Vec0xd50.ExtSnsFrdData>? = null,
@ProtoId(11) val over: Int = 0,
@ProtoId(12) val nextStart: Int = 0,
@ProtoId(13) val uint64UnfinishedUins: List<Long>? = null
) : ProtoBuf
@Serializable
internal class ReqBody(
@SerialId(1) val appid: Long = 0L,
@SerialId(2) val maxPkgSize: Int = 0,
@SerialId(3) val startTime: Int = 0,
@SerialId(4) val startIndex: Int = 0,
@SerialId(5) val reqNum: Int = 0,
@SerialId(6) val uinList: List<Long>? = null,
@SerialId(91001) val reqMusicSwitch: Int = 0,
@SerialId(101001) val reqMutualmarkAlienation: Int = 0,
@SerialId(141001) val reqMutualmarkScore: Int = 0,
@SerialId(151001) val reqKsingSwitch: Int = 0,
@SerialId(181001) val reqMutualmarkLbsshare: Int = 0
@ProtoId(1) val appid: Long = 0L,
@ProtoId(2) val maxPkgSize: Int = 0,
@ProtoId(3) val startTime: Int = 0,
@ProtoId(4) val startIndex: Int = 0,
@ProtoId(5) val reqNum: Int = 0,
@ProtoId(6) val uinList: List<Long>? = null,
@ProtoId(91001) val reqMusicSwitch: Int = 0,
@ProtoId(101001) val reqMutualmarkAlienation: Int = 0,
@ProtoId(141001) val reqMutualmarkScore: Int = 0,
@ProtoId(151001) val reqKsingSwitch: Int = 0,
@ProtoId(181001) val reqMutualmarkLbsshare: Int = 0
) : ProtoBuf
@Serializable
internal class KSingRelationInfo(
@SerialId(1) val flag: Int = 0
@ProtoId(1) val flag: Int = 0
) : ProtoBuf
}
@ -59,21 +59,21 @@ internal class Vec0xd50 : ProtoBuf {
internal class Vec0xd6b : ProtoBuf {
@Serializable
internal class ReqBody(
@SerialId(1) val maxPkgSize: Int = 0,
@SerialId(2) val startTime: Int = 0,
@SerialId(11) val uinList: List<Long>? = null
@ProtoId(1) val maxPkgSize: Int = 0,
@ProtoId(2) val startTime: Int = 0,
@ProtoId(11) val uinList: List<Long>? = null
) : ProtoBuf
@Serializable
internal class RspBody(
@SerialId(11) val msgMutualmarkData: List<Vec0xd6b.MutualMarkData>? = null,
@SerialId(12) val uint64UnfinishedUins: List<Long>? = null
@ProtoId(11) val msgMutualmarkData: List<Vec0xd6b.MutualMarkData>? = null,
@ProtoId(12) val uint64UnfinishedUins: List<Long>? = null
) : ProtoBuf
@Serializable
internal class MutualMarkData(
@SerialId(1) val frdUin: Long = 0L,
@SerialId(2) val result: Int = 0
@ProtoId(1) val frdUin: Long = 0L,
@ProtoId(2) val result: Int = 0
// @SerialId(11) val mutualmarkInfo: List<Mutualmark.MutualMark>? = null
) : ProtoBuf
}
@ -82,26 +82,26 @@ internal class Vec0xd6b : ProtoBuf {
internal class Mutualmark : ProtoBuf {
@Serializable
internal class MutualmarkInfo(
@SerialId(1) val lastActionTime: Long = 0L,
@SerialId(2) val level: Int = 0,
@SerialId(3) val lastChangeTime: Long = 0L,
@SerialId(4) val continueDays: Int = 0,
@SerialId(5) val wildcardWording: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val notifyTime: Long = 0L,
@SerialId(7) val iconStatus: Long = 0L,
@SerialId(8) val iconStatusEndTime: Long = 0L,
@SerialId(9) val closeFlag: Int = 0,
@SerialId(10) val resourceInfo: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val lastActionTime: Long = 0L,
@ProtoId(2) val level: Int = 0,
@ProtoId(3) val lastChangeTime: Long = 0L,
@ProtoId(4) val continueDays: Int = 0,
@ProtoId(5) val wildcardWording: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val notifyTime: Long = 0L,
@ProtoId(7) val iconStatus: Long = 0L,
@ProtoId(8) val iconStatusEndTime: Long = 0L,
@ProtoId(9) val closeFlag: Int = 0,
@ProtoId(10) val resourceInfo: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
internal class ResourceInfo17(
@SerialId(1) val dynamicUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val staticUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val cartoonUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val cartoonMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val playCartoon: Int = 0,
@SerialId(6) val word: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val dynamicUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val staticUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val cartoonUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val cartoonMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val playCartoon: Int = 0,
@ProtoId(6) val word: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
}

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@ -18,51 +18,51 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
class GroupLabel : ProtoBuf {
@Serializable
class Label(
@SerialId(1) val name: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val enumType: Int /* enum */ = 1,
@SerialId(3) val textColor: GroupLabel.Color? = null,
@SerialId(4) val edgingColor: GroupLabel.Color? = null,
@SerialId(5) val labelAttr: Int = 0,
@SerialId(6) val labelType: Int = 0
@ProtoId(1) val name: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val enumType: Int /* enum */ = 1,
@ProtoId(3) val textColor: GroupLabel.Color? = null,
@ProtoId(4) val edgingColor: GroupLabel.Color? = null,
@ProtoId(5) val labelAttr: Int = 0,
@ProtoId(6) val labelType: Int = 0
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1) val error: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val groupInfo: List<GroupLabel.GroupInfo>? = null
@ProtoId(1) val error: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val groupInfo: List<GroupLabel.GroupInfo>? = null
) : ProtoBuf
@Serializable
class SourceId(
@SerialId(1) val sourceId: Int = 0
@ProtoId(1) val sourceId: Int = 0
) : ProtoBuf
@Serializable
class GroupInfo(
@SerialId(1) val int32Result: Int = 0,
@SerialId(2) val groupCode: Long = 0L,
@SerialId(3) val groupLabel: List<GroupLabel.Label>? = null
@ProtoId(1) val int32Result: Int = 0,
@ProtoId(2) val groupCode: Long = 0L,
@ProtoId(3) val groupLabel: List<GroupLabel.Label>? = null
) : ProtoBuf
@Serializable
class Color(
@SerialId(1) val r: Int = 0,
@SerialId(2) val g: Int = 0,
@SerialId(3) val b: Int = 0
@ProtoId(1) val r: Int = 0,
@ProtoId(2) val g: Int = 0,
@ProtoId(3) val b: Int = 0
) : ProtoBuf
@Serializable
class ReqBody(
@SerialId(1) val sourceId: GroupLabel.SourceId? = null,
@SerialId(2) val uinInfo: GroupLabel.UinInfo? = null,
@SerialId(3) val numberLabel: Int = 5,
@SerialId(4) val groupCode: List<Long>? = null,
@SerialId(5) val labelStyle: Int = 0
@ProtoId(1) val sourceId: GroupLabel.SourceId? = null,
@ProtoId(2) val uinInfo: GroupLabel.UinInfo? = null,
@ProtoId(3) val numberLabel: Int = 5,
@ProtoId(4) val groupCode: List<Long>? = null,
@ProtoId(5) val labelStyle: Int = 0
) : ProtoBuf
@Serializable
class UinInfo(
@SerialId(1) val int64Longitude: Long = 0L,
@SerialId(2) val int64Latitude: Long = 0L
@ProtoId(1) val int64Longitude: Long = 0L,
@ProtoId(2) val int64Latitude: Long = 0L
) : ProtoBuf
}

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import kotlinx.serialization.protobuf.ProtoNumberType
import kotlinx.serialization.protobuf.ProtoType
import net.mamoe.mirai.qqandroid.io.ProtoBuf
@ -20,90 +20,90 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
class BdhExtinfo : ProtoBuf {
@Serializable
class CommFileExtReq(
@SerialId(1) val actionType: Int = 0,
@SerialId(2) val uuid: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val actionType: Int = 0,
@ProtoId(2) val uuid: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class CommFileExtRsp(
@SerialId(1) val int32Retcode: Int = 0,
@SerialId(2) val downloadUrl: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val int32Retcode: Int = 0,
@ProtoId(2) val downloadUrl: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class PicInfo(
@SerialId(1) val idx: Int = 0,
@SerialId(2) val size: Int = 0,
@SerialId(3) val binMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val type: Int = 0
@ProtoId(1) val idx: Int = 0,
@ProtoId(2) val size: Int = 0,
@ProtoId(3) val binMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val type: Int = 0
) : ProtoBuf
@Serializable
class QQVoiceExtReq(
@SerialId(1) val qid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val fmt: Int = 0,
@SerialId(3) val rate: Int = 0,
@SerialId(4) val bits: Int = 0,
@SerialId(5) val channel: Int = 0,
@SerialId(6) val pinyin: Int = 0
@ProtoId(1) val qid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val fmt: Int = 0,
@ProtoId(3) val rate: Int = 0,
@ProtoId(4) val bits: Int = 0,
@ProtoId(5) val channel: Int = 0,
@ProtoId(6) val pinyin: Int = 0
) : ProtoBuf
@Serializable
class QQVoiceExtRsp(
@SerialId(1) val qid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val int32Retcode: Int = 0,
@SerialId(3) val msgResult: List<QQVoiceResult>? = null
@ProtoId(1) val qid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val int32Retcode: Int = 0,
@ProtoId(3) val msgResult: List<QQVoiceResult>? = null
) : ProtoBuf
@Serializable
class QQVoiceResult(
@SerialId(1) val text: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val pinyin: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val source: Int = 0
@ProtoId(1) val text: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val pinyin: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val source: Int = 0
) : ProtoBuf
@Serializable
class ShortVideoReqExtInfo(
@SerialId(1) val cmd: Int = 0,
@SerialId(2) val sessionId: Long = 0L,
@SerialId(3) val msgThumbinfo: PicInfo? = null,
@SerialId(4) val msgVideoinfo: VideoInfo? = null,
@SerialId(5) val msgShortvideoSureReq: ShortVideoSureReqInfo? = null,
@SerialId(6) val boolIsMergeCmdBeforeData: Boolean = false
@ProtoId(1) val cmd: Int = 0,
@ProtoId(2) val sessionId: Long = 0L,
@ProtoId(3) val msgThumbinfo: PicInfo? = null,
@ProtoId(4) val msgVideoinfo: VideoInfo? = null,
@ProtoId(5) val msgShortvideoSureReq: ShortVideoSureReqInfo? = null,
@ProtoId(6) val boolIsMergeCmdBeforeData: Boolean = false
) : ProtoBuf
@Serializable
class ShortVideoRspExtInfo(
@SerialId(1) val cmd: Int = 0,
@SerialId(2) val sessionId: Long = 0L,
@SerialId(3) val int32Retcode: Int = 0,
@SerialId(4) val errinfo: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val msgThumbinfo: PicInfo? = null,
@SerialId(6) val msgVideoinfo: VideoInfo? = null,
@SerialId(7) val msgShortvideoSureRsp: ShortVideoSureRspInfo? = null,
@SerialId(8) val retryFlag: Int = 0
@ProtoId(1) val cmd: Int = 0,
@ProtoId(2) val sessionId: Long = 0L,
@ProtoId(3) val int32Retcode: Int = 0,
@ProtoId(4) val errinfo: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val msgThumbinfo: PicInfo? = null,
@ProtoId(6) val msgVideoinfo: VideoInfo? = null,
@ProtoId(7) val msgShortvideoSureRsp: ShortVideoSureRspInfo? = null,
@ProtoId(8) val retryFlag: Int = 0
) : ProtoBuf
@Serializable
class ShortVideoSureReqInfo(
@SerialId(1) val fromuin: Long = 0L,
@SerialId(2) val chatType: Int = 0,
@SerialId(3) val touin: Long = 0L,
@SerialId(4) val groupCode: Long = 0L,
@SerialId(5) val clientType: Int = 0,
@SerialId(6) val msgThumbinfo: PicInfo? = null,
@SerialId(7) val msgMergeVideoinfo: List<VideoInfo>? = null,
@SerialId(8) val msgDropVideoinfo: List<VideoInfo>? = null,
@SerialId(9) val businessType: Int = 0,
@SerialId(10) val subBusinessType: Int = 0
@ProtoId(1) val fromuin: Long = 0L,
@ProtoId(2) val chatType: Int = 0,
@ProtoId(3) val touin: Long = 0L,
@ProtoId(4) val groupCode: Long = 0L,
@ProtoId(5) val clientType: Int = 0,
@ProtoId(6) val msgThumbinfo: PicInfo? = null,
@ProtoId(7) val msgMergeVideoinfo: List<VideoInfo>? = null,
@ProtoId(8) val msgDropVideoinfo: List<VideoInfo>? = null,
@ProtoId(9) val businessType: Int = 0,
@ProtoId(10) val subBusinessType: Int = 0
) : ProtoBuf
@Serializable
class ShortVideoSureRspInfo(
@SerialId(1) val fileid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val ukey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val msgVideoinfo: VideoInfo? = null,
@SerialId(4) val mergeCost: Int = 0
@ProtoId(1) val fileid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val ukey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val msgVideoinfo: VideoInfo? = null,
@ProtoId(4) val mergeCost: Int = 0
) : ProtoBuf
@Serializable
@ -111,31 +111,31 @@ class BdhExtinfo : ProtoBuf {
@Serializable
class StoryVideoExtRsp(
@SerialId(1) val int32Retcode: Int = 0,
@SerialId(2) val msg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val cdnUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val fileId: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val int32Retcode: Int = 0,
@ProtoId(2) val msg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val cdnUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val fileId: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class UploadPicExtInfo(
@SerialId(1) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val downloadUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val thumbDownloadUrl: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val fileResid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val downloadUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val thumbDownloadUrl: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class VideoInfo(
@SerialId(1) val idx: Int = 0,
@SerialId(2) val size: Int = 0,
@SerialId(3) val binMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val format: Int = 0,
@SerialId(5) val resLen: Int = 0,
@SerialId(6) val resWidth: Int = 0,
@SerialId(7) val time: Int = 0,
@SerialId(8) val starttime: Long = 0L,
@SerialId(9) val isAudio: Int = 0
@ProtoId(1) val idx: Int = 0,
@ProtoId(2) val size: Int = 0,
@ProtoId(3) val binMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val format: Int = 0,
@ProtoId(5) val resLen: Int = 0,
@ProtoId(6) val resWidth: Int = 0,
@ProtoId(7) val time: Int = 0,
@ProtoId(8) val starttime: Long = 0L,
@ProtoId(9) val isAudio: Int = 0
) : ProtoBuf
}
@ -143,142 +143,142 @@ class BdhExtinfo : ProtoBuf {
class CSDataHighwayHead : ProtoBuf {
@Serializable
class C2CCommonExtendinfo(
@SerialId(1) val infoId: Int = 0,
@SerialId(2) val msgFilterExtendinfo: FilterExtendinfo? = null
@ProtoId(1) val infoId: Int = 0,
@ProtoId(2) val msgFilterExtendinfo: FilterExtendinfo? = null
) : ProtoBuf
@Serializable
class DataHighwayHead(
@SerialId(1) val version: Int = 0,
@SerialId(2) val uin: String = "", // yes
@SerialId(3) val command: String = "",
@SerialId(4) val seq: Int = 0,
@SerialId(5) val retryTimes: Int = 0,
@SerialId(6) val appid: Int = 0,
@SerialId(7) val dataflag: Int = 0,
@SerialId(8) val commandId: Int = 0,
@SerialId(9) val buildVer: String = "",
@SerialId(10) val localeId: Int = 0
@ProtoId(1) val version: Int = 0,
@ProtoId(2) val uin: String = "", // yes
@ProtoId(3) val command: String = "",
@ProtoId(4) val seq: Int = 0,
@ProtoId(5) val retryTimes: Int = 0,
@ProtoId(6) val appid: Int = 0,
@ProtoId(7) val dataflag: Int = 0,
@ProtoId(8) val commandId: Int = 0,
@ProtoId(9) val buildVer: String = "",
@ProtoId(10) val localeId: Int = 0
) : ProtoBuf
@Serializable
class DataHole(
@SerialId(1) val begin: Long = 0L,
@SerialId(2) val end: Long = 0L
@ProtoId(1) val begin: Long = 0L,
@ProtoId(2) val end: Long = 0L
) : ProtoBuf
@Serializable
class FilterExtendinfo(
@SerialId(1) val filterFlag: Int = 0,
@SerialId(2) val msgImageFilterRequest: ImageFilterRequest? = null
@ProtoId(1) val filterFlag: Int = 0,
@ProtoId(2) val msgImageFilterRequest: ImageFilterRequest? = null
) : ProtoBuf
@Serializable
class FilterStyle(
@SerialId(1) val styleId: Int = 0,
@SerialId(2) val styleName: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val styleId: Int = 0,
@ProtoId(2) val styleName: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ImageFilterRequest(
@SerialId(1) val sessionId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val clientIp: Int = 0,
@SerialId(3) val uin: Long = 0L,
@SerialId(4) val style: FilterStyle? = null,
@SerialId(5) val width: Int = 0,
@SerialId(6) val height: Int = 0,
@SerialId(7) val imageData: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val sessionId: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val clientIp: Int = 0,
@ProtoId(3) val uin: Long = 0L,
@ProtoId(4) val style: FilterStyle? = null,
@ProtoId(5) val width: Int = 0,
@ProtoId(6) val height: Int = 0,
@ProtoId(7) val imageData: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ImageFilterResponse(
@SerialId(1) val retCode: Int = 0,
@SerialId(2) val imageData: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val costTime: Int = 0
@ProtoId(1) val retCode: Int = 0,
@ProtoId(2) val imageData: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val costTime: Int = 0
) : ProtoBuf
@Serializable
class LoginSigHead(
@SerialId(1) val loginsigType: Int = 0,
@SerialId(2) val loginsig: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val loginsigType: Int = 0,
@ProtoId(2) val loginsig: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class NewServiceTicket(
@SerialId(1) val signature: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val ukey: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val signature: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val ukey: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class PicInfoExt(
@SerialId(1) val picWidth: Int = 0,
@SerialId(2) val picHeight: Int = 0,
@SerialId(3) val picFlag: Int = 0,
@SerialId(4) val busiType: Int = 0,
@SerialId(5) val srcTerm: Int = 0,
@SerialId(6) val platType: Int = 0,
@SerialId(7) val netType: Int = 0,
@SerialId(8) val imgType: Int = 0,
@SerialId(9) val appPicType: Int = 0
@ProtoId(1) val picWidth: Int = 0,
@ProtoId(2) val picHeight: Int = 0,
@ProtoId(3) val picFlag: Int = 0,
@ProtoId(4) val busiType: Int = 0,
@ProtoId(5) val srcTerm: Int = 0,
@ProtoId(6) val platType: Int = 0,
@ProtoId(7) val netType: Int = 0,
@ProtoId(8) val imgType: Int = 0,
@ProtoId(9) val appPicType: Int = 0
) : ProtoBuf
@Serializable
class PicRspExtInfo(
@SerialId(1) val skey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val clientIp: Int = 0,
@SerialId(3) val upOffset: Long = 0L,
@SerialId(4) val blockSize: Long = 0L
@ProtoId(1) val skey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val clientIp: Int = 0,
@ProtoId(3) val upOffset: Long = 0L,
@ProtoId(4) val blockSize: Long = 0L
) : ProtoBuf
@Serializable
class QueryHoleRsp(
@SerialId(1) val result: Int = 0,
@SerialId(2) val dataHole: List<DataHole>? = null,
@SerialId(3) val boolCompFlag: Boolean = false
@ProtoId(1) val result: Int = 0,
@ProtoId(2) val dataHole: List<DataHole>? = null,
@ProtoId(3) val boolCompFlag: Boolean = false
) : ProtoBuf
@Serializable
class ReqDataHighwayHead(
@SerialId(1) val msgBasehead: DataHighwayHead? = null,
@SerialId(2) val msgSeghead: SegHead? = null,
@SerialId(3) val reqExtendinfo: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val timestamp: Long = 0L,
@SerialId(5) val msgLoginSigHead: LoginSigHead? = null
@ProtoId(1) val msgBasehead: DataHighwayHead? = null,
@ProtoId(2) val msgSeghead: SegHead? = null,
@ProtoId(3) val reqExtendinfo: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val timestamp: Long = 0L,
@ProtoId(5) val msgLoginSigHead: LoginSigHead? = null
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1) val msgQueryHoleRsp: QueryHoleRsp? = null
@ProtoId(1) val msgQueryHoleRsp: QueryHoleRsp? = null
) : ProtoBuf
@Serializable
class RspDataHighwayHead(
@SerialId(1) val msgBasehead: DataHighwayHead? = null,
@SerialId(2) val msgSeghead: SegHead? = null,
@SerialId(3) val errorCode: Int = 0,
@SerialId(4) val allowRetry: Int = 0,
@SerialId(5) val cachecost: Int = 0,
@SerialId(6) val htcost: Int = 0,
@SerialId(7) val rspExtendinfo: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val timestamp: Long = 0L,
@SerialId(9) val range: Long = 0L,
@SerialId(10) val isReset: Int = 0
@ProtoId(1) val msgBasehead: DataHighwayHead? = null,
@ProtoId(2) val msgSeghead: SegHead? = null,
@ProtoId(3) val errorCode: Int = 0,
@ProtoId(4) val allowRetry: Int = 0,
@ProtoId(5) val cachecost: Int = 0,
@ProtoId(6) val htcost: Int = 0,
@ProtoId(7) val rspExtendinfo: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(8) val timestamp: Long = 0L,
@ProtoId(9) val range: Long = 0L,
@ProtoId(10) val isReset: Int = 0
) : ProtoBuf
@Serializable
class SegHead(
@SerialId(1) val serviceid: Int = 0,
@SerialId(2) val filesize: Long = 0L,
@SerialId(3) val dataoffset: Long = 0L,
@SerialId(4) val datalength: Int = 0,
@SerialId(5) val rtcode: Int = 0,
@SerialId(6) val serviceticket: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val flag: Int = 0,
@SerialId(8) val md5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val cacheAddr: Int = 0,
@SerialId(11) val queryTimes: Int = 0,
@SerialId(12) val updateCacheip: Int = 0
@ProtoId(1) val serviceid: Int = 0,
@ProtoId(2) val filesize: Long = 0L,
@ProtoId(3) val dataoffset: Long = 0L,
@ProtoId(4) val datalength: Int = 0,
@ProtoId(5) val rtcode: Int = 0,
@ProtoId(6) val serviceticket: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(7) val flag: Int = 0,
@ProtoId(8) val md5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(9) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(10) val cacheAddr: Int = 0,
@ProtoId(11) val queryTimes: Int = 0,
@ProtoId(12) val updateCacheip: Int = 0
) : ProtoBuf
}
@ -286,31 +286,31 @@ class CSDataHighwayHead : ProtoBuf {
class HwConfigPersistentPB : ProtoBuf {
@Serializable
class HwConfigItemPB(
@SerialId(1) val ingKey: String = "",
@SerialId(2) val endPointList: List<HwEndPointPB>? = null
@ProtoId(1) val ingKey: String = "",
@ProtoId(2) val endPointList: List<HwEndPointPB>? = null
) : ProtoBuf
@Serializable
class HwConfigPB(
@SerialId(1) val configItemList: List<HwConfigItemPB>? = null,
@SerialId(2) val netSegConfList: List<HwNetSegConfPB>? = null,
@SerialId(3) val shortVideoNetConf: List<HwNetSegConfPB>? = null,
@SerialId(4) val configItemListIp6: List<HwConfigItemPB>? = null
@ProtoId(1) val configItemList: List<HwConfigItemPB>? = null,
@ProtoId(2) val netSegConfList: List<HwNetSegConfPB>? = null,
@ProtoId(3) val shortVideoNetConf: List<HwNetSegConfPB>? = null,
@ProtoId(4) val configItemListIp6: List<HwConfigItemPB>? = null
) : ProtoBuf
@Serializable
class HwEndPointPB(
@SerialId(1) val ingHost: String = "",
@SerialId(2) val int32Port: Int = 0,
@SerialId(3) val int64Timestampe: Long = 0L
@ProtoId(1) val ingHost: String = "",
@ProtoId(2) val int32Port: Int = 0,
@ProtoId(3) val int64Timestampe: Long = 0L
) : ProtoBuf
@Serializable
class HwNetSegConfPB(
@SerialId(1) val int64NetType: Long = 0L,
@SerialId(2) val int64SegSize: Long = 0L,
@SerialId(3) val int64SegNum: Long = 0L,
@SerialId(4) val int64CurConnNum: Long = 0L
@ProtoId(1) val int64NetType: Long = 0L,
@ProtoId(2) val int64SegSize: Long = 0L,
@ProtoId(3) val int64SegNum: Long = 0L,
@ProtoId(4) val int64CurConnNum: Long = 0L
) : ProtoBuf
}
@ -318,8 +318,8 @@ class HwConfigPersistentPB : ProtoBuf {
class HwSessionInfoPersistentPB : ProtoBuf {
@Serializable
class HwSessionInfoPB(
@SerialId(1) val httpconnSigSession: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val sessionKey: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val httpconnSigSession: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val sessionKey: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
}
@ -327,137 +327,137 @@ class HwSessionInfoPersistentPB : ProtoBuf {
class Subcmd0x501 : ProtoBuf {
@Serializable
class ReqBody(
@SerialId(1281) val msgSubcmd0x501ReqBody: SubCmd0x501ReqBody? = null
@ProtoId(1281) val msgSubcmd0x501ReqBody: SubCmd0x501ReqBody? = null
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1281) val msgSubcmd0x501RspBody: SubCmd0x501Rspbody? = null
@ProtoId(1281) val msgSubcmd0x501RspBody: SubCmd0x501Rspbody? = null
) : ProtoBuf
@Serializable
class SubCmd0x501ReqBody(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val idcId: Int = 0,
@SerialId(3) val appid: Int = 0,
@SerialId(4) val loginSigType: Int = 0,
@SerialId(5) val loginSigTicket: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val requestFlag: Int = 0,
@SerialId(7) val uint32ServiceTypes: List<Int>? = null,
@SerialId(8) val bid: Int = 0,
@SerialId(9) val term: Int = 0,
@SerialId(10) val plat: Int = 0,
@SerialId(11) val net: Int = 0,
@SerialId(12) val caller: Int = 0
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val idcId: Int = 0,
@ProtoId(3) val appid: Int = 0,
@ProtoId(4) val loginSigType: Int = 0,
@ProtoId(5) val loginSigTicket: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val requestFlag: Int = 0,
@ProtoId(7) val uint32ServiceTypes: List<Int>? = null,
@ProtoId(8) val bid: Int = 0,
@ProtoId(9) val term: Int = 0,
@ProtoId(10) val plat: Int = 0,
@ProtoId(11) val net: Int = 0,
@ProtoId(12) val caller: Int = 0
) : ProtoBuf
@Serializable
class SubCmd0x501Rspbody(
@SerialId(1) val httpconnSigSession: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val sessionKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val msgHttpconnAddrs: List<SrvAddrs>? = null,
@SerialId(4) val preConnection: Int = 0,
@SerialId(5) val csConn: Int = 0,
@SerialId(6) val msgIpLearnConf: IpLearnConf? = null,
@SerialId(7) val msgDynTimeoutConf: DynTimeOutConf? = null,
@SerialId(8) val msgOpenUpConf: OpenUpConf? = null,
@SerialId(9) val msgDownloadEncryptConf: DownloadEncryptConf? = null,
@SerialId(10) val msgShortVideoConf: ShortVideoConf? = null,
@SerialId(11) val msgPtvConf: PTVConf? = null
@ProtoId(1) val httpconnSigSession: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val sessionKey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val msgHttpconnAddrs: List<SrvAddrs>? = null,
@ProtoId(4) val preConnection: Int = 0,
@ProtoId(5) val csConn: Int = 0,
@ProtoId(6) val msgIpLearnConf: IpLearnConf? = null,
@ProtoId(7) val msgDynTimeoutConf: DynTimeOutConf? = null,
@ProtoId(8) val msgOpenUpConf: OpenUpConf? = null,
@ProtoId(9) val msgDownloadEncryptConf: DownloadEncryptConf? = null,
@ProtoId(10) val msgShortVideoConf: ShortVideoConf? = null,
@ProtoId(11) val msgPtvConf: PTVConf? = null
) : ProtoBuf {
@Serializable
class DownloadEncryptConf(
@SerialId(1) val boolEnableEncryptRequest: Boolean = false,
@SerialId(2) val boolEnableEncryptedPic: Boolean = false,
@SerialId(3) val ctrlFlag: Int = 0
@ProtoId(1) val boolEnableEncryptRequest: Boolean = false,
@ProtoId(2) val boolEnableEncryptedPic: Boolean = false,
@ProtoId(3) val ctrlFlag: Int = 0
) : ProtoBuf
@Serializable
class DynTimeOutConf(
@SerialId(1) val tbase2g: Int = 0,
@SerialId(2) val tbase3g: Int = 0,
@SerialId(3) val tbase4g: Int = 0,
@SerialId(4) val tbaseWifi: Int = 0,
@SerialId(5) val torg2g: Int = 0,
@SerialId(6) val torg3g: Int = 0,
@SerialId(7) val torg4g: Int = 0,
@SerialId(8) val torgWifi: Int = 0,
@SerialId(9) val maxTimeout: Int = 0,
@SerialId(10) val enableDynTimeout: Int = 0,
@SerialId(11) val maxTimeout2g: Int = 0,
@SerialId(12) val maxTimeout3g: Int = 0,
@SerialId(13) val maxTimeout4g: Int = 0,
@SerialId(14) val maxTimeoutWifi: Int = 0,
@SerialId(15) val hbTimeout2g: Int = 0,
@SerialId(16) val hbTimeout3g: Int = 0,
@SerialId(17) val hbTimeout4g: Int = 0,
@SerialId(18) val hbTimeoutWifi: Int = 0,
@SerialId(19) val hbTimeoutDefault: Int = 0
@ProtoId(1) val tbase2g: Int = 0,
@ProtoId(2) val tbase3g: Int = 0,
@ProtoId(3) val tbase4g: Int = 0,
@ProtoId(4) val tbaseWifi: Int = 0,
@ProtoId(5) val torg2g: Int = 0,
@ProtoId(6) val torg3g: Int = 0,
@ProtoId(7) val torg4g: Int = 0,
@ProtoId(8) val torgWifi: Int = 0,
@ProtoId(9) val maxTimeout: Int = 0,
@ProtoId(10) val enableDynTimeout: Int = 0,
@ProtoId(11) val maxTimeout2g: Int = 0,
@ProtoId(12) val maxTimeout3g: Int = 0,
@ProtoId(13) val maxTimeout4g: Int = 0,
@ProtoId(14) val maxTimeoutWifi: Int = 0,
@ProtoId(15) val hbTimeout2g: Int = 0,
@ProtoId(16) val hbTimeout3g: Int = 0,
@ProtoId(17) val hbTimeout4g: Int = 0,
@ProtoId(18) val hbTimeoutWifi: Int = 0,
@ProtoId(19) val hbTimeoutDefault: Int = 0
) : ProtoBuf
@Serializable
class Ip6Addr(
@SerialId(1) val type: Int = 0,
@SerialId(2) val ip6: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val port: Int = 0,
@SerialId(4) val area: Int = 0,
@SerialId(5) val sameIsp: Int = 0
@ProtoId(1) val type: Int = 0,
@ProtoId(2) val ip6: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val port: Int = 0,
@ProtoId(4) val area: Int = 0,
@ProtoId(5) val sameIsp: Int = 0
) : ProtoBuf
@Serializable
class IpAddr(
@SerialId(1) val type: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(2) val ip: Int = 0,
@SerialId(3) val port: Int = 0,
@SerialId(4) val area: Int = 0,
@SerialId(5) val sameIsp: Int = 0
@ProtoId(1) val type: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @ProtoId(2) val ip: Int = 0,
@ProtoId(3) val port: Int = 0,
@ProtoId(4) val area: Int = 0,
@ProtoId(5) val sameIsp: Int = 0
) : ProtoBuf
@Serializable
class IpLearnConf(
@SerialId(1) val refreshCachedIp: Int = 0,
@SerialId(2) val enableIpLearn: Int = 0
@ProtoId(1) val refreshCachedIp: Int = 0,
@ProtoId(2) val enableIpLearn: Int = 0
) : ProtoBuf
@Serializable
class NetSegConf(
@SerialId(1) val netType: Int = 0,
@SerialId(2) val segsize: Int = 0,
@SerialId(3) val segnum: Int = 0,
@SerialId(4) val curconnnum: Int = 0
@ProtoId(1) val netType: Int = 0,
@ProtoId(2) val segsize: Int = 0,
@ProtoId(3) val segnum: Int = 0,
@ProtoId(4) val curconnnum: Int = 0
) : ProtoBuf
@Serializable
class OpenUpConf(
@SerialId(1) val boolEnableOpenup: Boolean = false,
@SerialId(2) val preSendSegnum: Int = 0,
@SerialId(3) val preSendSegnum3g: Int = 0,
@SerialId(4) val preSendSegnum4g: Int = 0,
@SerialId(5) val preSendSegnumWifi: Int = 0
@ProtoId(1) val boolEnableOpenup: Boolean = false,
@ProtoId(2) val preSendSegnum: Int = 0,
@ProtoId(3) val preSendSegnum3g: Int = 0,
@ProtoId(4) val preSendSegnum4g: Int = 0,
@ProtoId(5) val preSendSegnumWifi: Int = 0
) : ProtoBuf
@Serializable
class PTVConf(
@SerialId(1) val channelType: Int = 0,
@SerialId(2) val msgNetsegconf: List<NetSegConf>? = null,
@SerialId(3) val boolOpenHardwareCodec: Boolean = false
@ProtoId(1) val channelType: Int = 0,
@ProtoId(2) val msgNetsegconf: List<NetSegConf>? = null,
@ProtoId(3) val boolOpenHardwareCodec: Boolean = false
) : ProtoBuf
@Serializable
class ShortVideoConf(
@SerialId(1) val channelType: Int = 0,
@SerialId(2) val msgNetsegconf: List<NetSegConf>? = null,
@SerialId(3) val boolOpenHardwareCodec: Boolean = false,
@SerialId(4) val boolSendAheadSignal: Boolean = false
@ProtoId(1) val channelType: Int = 0,
@ProtoId(2) val msgNetsegconf: List<NetSegConf>? = null,
@ProtoId(3) val boolOpenHardwareCodec: Boolean = false,
@ProtoId(4) val boolSendAheadSignal: Boolean = false
) : ProtoBuf
@Serializable
class SrvAddrs(
@SerialId(1) val serviceType: Int = 0,
@SerialId(2) val msgAddrs: List<IpAddr>? = null,
@SerialId(3) val fragmentSize: Int = 0,
@SerialId(4) val msgNetsegconf: List<NetSegConf>? = null,
@SerialId(5) val msgAddrsV6: List<Ip6Addr>? = null
@ProtoId(1) val serviceType: Int = 0,
@ProtoId(2) val msgAddrs: List<IpAddr>? = null,
@ProtoId(3) val fragmentSize: Int = 0,
@ProtoId(4) val msgNetsegconf: List<NetSegConf>? = null,
@ProtoId(5) val msgAddrsV6: List<Ip6Addr>? = null
) : ProtoBuf
}
}

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.utils.currentTimeSeconds
@ -20,22 +20,22 @@ interface ImgReq : ProtoBuf
@Serializable
internal class GetImgUrlReq(
@SerialId(1) val srcUni: Int,
@SerialId(2) val dstUni: Int,
@SerialId(3) val fileResID: String,//UUID
@ProtoId(1) val srcUni: Int,
@ProtoId(2) val dstUni: Int,
@ProtoId(3) val fileResID: String,//UUID
/**
* UUID例子: 没有找到
*/
@SerialId(4) val urlFlag: Int = 1,
@ProtoId(4) val urlFlag: Int = 1,
//5 unknown, 好像没用
@SerialId(6) val urlType: Int = 4,
@SerialId(7) val requestTerm: Int = 5,//确定
@SerialId(8) val requestPlatformType: Int = 9,//确定
@SerialId(9) val srcFileType: Int = 1,//2=ftn1=picplatform255
@SerialId(10) val innerIP: Int = 0,//确定
@SerialId(11) val addressBook: Int = 0,//[ChatType.internalID]== 1006为1[为CONTACT时] 我觉得发0没问题
@SerialId(12) val buType: Int = 1,//确定
@SerialId(13) val buildVer: String = "8.2.7.4410",//版本号
@SerialId(14) val timestamp: Int = currentTimeSeconds.toInt(),//(pic_up_timestamp)
@SerialId(15) val requestTransferType: Int = 1
@ProtoId(6) val urlType: Int = 4,
@ProtoId(7) val requestTerm: Int = 5,//确定
@ProtoId(8) val requestPlatformType: Int = 9,//确定
@ProtoId(9) val srcFileType: Int = 1,//2=ftn1=picplatform255
@ProtoId(10) val innerIP: Int = 0,//确定
@ProtoId(11) val addressBook: Int = 0,//[ChatType.internalID]== 1006为1[为CONTACT时] 我觉得发0没问题
@ProtoId(12) val buType: Int = 1,//确定
@ProtoId(13) val buildVer: String = "8.2.7.4410",//版本号
@ProtoId(14) val timestamp: Int = currentTimeSeconds.toInt(),//(pic_up_timestamp)
@ProtoId(15) val requestTransferType: Int = 1
) : ImgReq

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@ -21,143 +21,143 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
internal class MsgComm : ProtoBuf {
@Serializable
internal class AppShareInfo(
@SerialId(1) val appshareId: Int = 0,
@SerialId(2) val appshareCookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val appshareResource: PluginInfo? = null
@ProtoId(1) val appshareId: Int = 0,
@ProtoId(2) val appshareCookie: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val appshareResource: PluginInfo? = null
) : ProtoBuf
@Serializable
internal class C2CTmpMsgHead(
@SerialId(1) val c2cType: Int = 0,
@SerialId(2) val serviceType: Int = 0,
@SerialId(3) val groupUin: Long = 0L,
@SerialId(4) val groupCode: Long = 0L,
@SerialId(5) val sig: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val sigType: Int = 0,
@SerialId(7) val fromPhone: String = "",
@SerialId(8) val toPhone: String = "",
@SerialId(9) val lockDisplay: Int = 0,
@SerialId(10) val directionFlag: Int = 0,
@SerialId(11) val reserved: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val c2cType: Int = 0,
@ProtoId(2) val serviceType: Int = 0,
@ProtoId(3) val groupUin: Long = 0L,
@ProtoId(4) val groupCode: Long = 0L,
@ProtoId(5) val sig: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val sigType: Int = 0,
@ProtoId(7) val fromPhone: String = "",
@ProtoId(8) val toPhone: String = "",
@ProtoId(9) val lockDisplay: Int = 0,
@ProtoId(10) val directionFlag: Int = 0,
@ProtoId(11) val reserved: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
internal class ContentHead(
@SerialId(1) val pkgNum: Int = 0,
@SerialId(2) val pkgIndex: Int = 0,
@SerialId(3) val divSeq: Int = 0,
@SerialId(4) val autoReply: Int = 0
@ProtoId(1) val pkgNum: Int = 0,
@ProtoId(2) val pkgIndex: Int = 0,
@ProtoId(3) val divSeq: Int = 0,
@ProtoId(4) val autoReply: Int = 0
) : ProtoBuf
@Serializable
internal class DiscussInfo(
@SerialId(1) val discussUin: Long = 0L,
@SerialId(2) val discussType: Int = 0,
@SerialId(3) val discussInfoSeq: Long = 0L,
@SerialId(4) val discussRemark: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val discussName: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val discussUin: Long = 0L,
@ProtoId(2) val discussType: Int = 0,
@ProtoId(3) val discussInfoSeq: Long = 0L,
@ProtoId(4) val discussRemark: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val discussName: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
internal class ExtGroupKeyInfo(
@SerialId(1) val curMaxSeq: Int = 0,
@SerialId(2) val curTime: Long = 0L
@ProtoId(1) val curMaxSeq: Int = 0,
@ProtoId(2) val curTime: Long = 0L
) : ProtoBuf
@Serializable
internal class GroupInfo(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val groupType: Int = 0,
@SerialId(3) val groupInfoSeq: Long = 0L,
@SerialId(4) val groupCard: String = "",
@SerialId(5) val groupRank: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val groupLevel: Int = 0,
@SerialId(7) val groupCardType: Int = 0,
@SerialId(8) val groupName: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val groupCode: Long = 0L,
@ProtoId(2) val groupType: Int = 0,
@ProtoId(3) val groupInfoSeq: Long = 0L,
@ProtoId(4) val groupCard: String = "",
@ProtoId(5) val groupRank: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(6) val groupLevel: Int = 0,
@ProtoId(7) val groupCardType: Int = 0,
@ProtoId(8) val groupName: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
internal class Msg(
@SerialId(1) val msgHead: MsgHead,
@SerialId(2) val contentHead: ContentHead? = null,
@SerialId(3) val msgBody: ImMsgBody.MsgBody,
@SerialId(4) val appshareInfo: AppShareInfo? = null
@ProtoId(1) val msgHead: MsgHead,
@ProtoId(2) val contentHead: ContentHead? = null,
@ProtoId(3) val msgBody: ImMsgBody.MsgBody,
@ProtoId(4) val appshareInfo: AppShareInfo? = null
) : ProtoBuf
@Serializable
internal class MsgHead(
@SerialId(1) val fromUin: Long = 0L,
@SerialId(2) val toUin: Long = 0L,
@SerialId(3) val msgType: Int = 0,
@SerialId(4) val c2cCmd: Int = 0,
@SerialId(5) val msgSeq: Int = 0,
@SerialId(6) val msgTime: Int = 0,
@SerialId(7) var msgUid: Long = 0L,
@SerialId(8) val c2cTmpMsgHead: C2CTmpMsgHead? = null,
@SerialId(9) val groupInfo: GroupInfo? = null,
@SerialId(10) val fromAppid: Int = 0,
@SerialId(11) val fromInstid: Int = 0,
@SerialId(12) val userActive: Int = 0,
@SerialId(13) val discussInfo: DiscussInfo? = null,
@SerialId(14) val fromNick: String = "",
@SerialId(15) val authUin: Long = 0L,
@SerialId(16) val authNick: String = "",
@SerialId(17) val msgFlag: Int = 0,
@SerialId(18) val authRemark: String = "",
@SerialId(19) val groupName: String = "",
@SerialId(20) val mutiltransHead: MutilTransHead? = null,
@SerialId(21) val msgInstCtrl: ImMsgHead.InstCtrl? = null,
@SerialId(22) val publicAccountGroupSendFlag: Int = 0,
@SerialId(23) val wseqInC2cMsghead: Int = 0,
@SerialId(24) val cpid: Long = 0L,
@SerialId(25) val extGroupKeyInfo: ExtGroupKeyInfo? = null,
@SerialId(26) val multiCompatibleText: String = "",
@SerialId(27) val authSex: Int = 0,
@SerialId(28) val isSrcMsg: Boolean = false
@ProtoId(1) val fromUin: Long = 0L,
@ProtoId(2) val toUin: Long = 0L,
@ProtoId(3) val msgType: Int = 0,
@ProtoId(4) val c2cCmd: Int = 0,
@ProtoId(5) val msgSeq: Int = 0,
@ProtoId(6) val msgTime: Int = 0,
@ProtoId(7) var msgUid: Long = 0L,
@ProtoId(8) val c2cTmpMsgHead: C2CTmpMsgHead? = null,
@ProtoId(9) val groupInfo: GroupInfo? = null,
@ProtoId(10) val fromAppid: Int = 0,
@ProtoId(11) val fromInstid: Int = 0,
@ProtoId(12) val userActive: Int = 0,
@ProtoId(13) val discussInfo: DiscussInfo? = null,
@ProtoId(14) val fromNick: String = "",
@ProtoId(15) val authUin: Long = 0L,
@ProtoId(16) val authNick: String = "",
@ProtoId(17) val msgFlag: Int = 0,
@ProtoId(18) val authRemark: String = "",
@ProtoId(19) val groupName: String = "",
@ProtoId(20) val mutiltransHead: MutilTransHead? = null,
@ProtoId(21) val msgInstCtrl: ImMsgHead.InstCtrl? = null,
@ProtoId(22) val publicAccountGroupSendFlag: Int = 0,
@ProtoId(23) val wseqInC2cMsghead: Int = 0,
@ProtoId(24) val cpid: Long = 0L,
@ProtoId(25) val extGroupKeyInfo: ExtGroupKeyInfo? = null,
@ProtoId(26) val multiCompatibleText: String = "",
@ProtoId(27) val authSex: Int = 0,
@ProtoId(28) val isSrcMsg: Boolean = false
) : ProtoBuf
@Serializable
internal class MsgType0x210(
@SerialId(1) val subMsgType: Int = 0,
@SerialId(2) val msgContent: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val subMsgType: Int = 0,
@ProtoId(2) val msgContent: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
internal class MutilTransHead(
@SerialId(1) val status: Int = 0,
@SerialId(2) val msgId: Int = 0
@ProtoId(1) val status: Int = 0,
@ProtoId(2) val msgId: Int = 0
) : ProtoBuf
@Serializable
internal class PluginInfo(
@SerialId(1) val resId: Int = 0,
@SerialId(2) val pkgName: String = "",
@SerialId(3) val newVer: Int = 0,
@SerialId(4) val resType: Int = 0,
@SerialId(5) val lanType: Int = 0,
@SerialId(6) val priority: Int = 0,
@SerialId(7) val resName: String = "",
@SerialId(8) val resDesc: String = "",
@SerialId(9) val resUrlBig: String = "",
@SerialId(10) val resUrlSmall: String = "",
@SerialId(11) val resConf: String = ""
@ProtoId(1) val resId: Int = 0,
@ProtoId(2) val pkgName: String = "",
@ProtoId(3) val newVer: Int = 0,
@ProtoId(4) val resType: Int = 0,
@ProtoId(5) val lanType: Int = 0,
@ProtoId(6) val priority: Int = 0,
@ProtoId(7) val resName: String = "",
@ProtoId(8) val resDesc: String = "",
@ProtoId(9) val resUrlBig: String = "",
@ProtoId(10) val resUrlSmall: String = "",
@ProtoId(11) val resConf: String = ""
) : ProtoBuf
@Serializable
internal class Uin2Nick(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val nick: String = ""
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val nick: String = ""
) : ProtoBuf
@Serializable
internal class UinPairMsg(
@SerialId(1) val lastReadTime: Int = 0,
@SerialId(2) val peerUin: Long = 0L,
@SerialId(3) val msgCompleted: Int = 0,
@SerialId(4) val msg: List<Msg>? = null,
@SerialId(5) val unreadMsgNum: Int = 0,
@SerialId(8) val c2cType: Int = 0,
@SerialId(9) val serviceType: Int = 0,
@SerialId(10) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val lastReadTime: Int = 0,
@ProtoId(2) val peerUin: Long = 0L,
@ProtoId(3) val msgCompleted: Int = 0,
@ProtoId(4) val msg: List<Msg>? = null,
@ProtoId(5) val unreadMsgNum: Int = 0,
@ProtoId(8) val c2cType: Int = 0,
@ProtoId(9) val serviceType: Int = 0,
@ProtoId(10) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
}

View File

@ -9,30 +9,30 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
class MsgRevokeUserDef : ProtoBuf {
@Serializable
class MsgInfoUserDef(
@SerialId(1) val longMessageFlag: Int = 0,
@SerialId(2) val longMsgInfo: List<MsgInfoDef>? = null,
@SerialId(3) val fileUuid: List<String> = listOf()
@ProtoId(1) val longMessageFlag: Int = 0,
@ProtoId(2) val longMsgInfo: List<MsgInfoDef>? = null,
@ProtoId(3) val fileUuid: List<String> = listOf()
) : ProtoBuf {
@Serializable
class MsgInfoDef(
@SerialId(1) val msgSeq: Int = 0,
@SerialId(2) val longMsgId: Int = 0,
@SerialId(3) val longMsgNum: Int = 0,
@SerialId(4) val longMsgIndex: Int = 0
@ProtoId(1) val msgSeq: Int = 0,
@ProtoId(2) val longMsgId: Int = 0,
@ProtoId(3) val longMsgNum: Int = 0,
@ProtoId(4) val longMsgIndex: Int = 0
) : ProtoBuf
}
@Serializable
class UinTypeUserDef(
@SerialId(1) val fromUinType: Int = 0,
@SerialId(2) val fromGroupCode: Long = 0L,
@SerialId(3) val fileUuid: List<String> = listOf()
@ProtoId(1) val fromUinType: Int = 0,
@ProtoId(2) val fromGroupCode: Long = 0L,
@ProtoId(3) val fileUuid: List<String> = listOf()
) : ProtoBuf
}

View File

@ -7,16 +7,16 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
class Oidb0x769 {
@Serializable
class RequestBody(
@SerialId(1) val rpt_config_list: List<ConfigSeq>
@ProtoId(1) val rpt_config_list: List<ConfigSeq>
// @SerialId(2) val msg_device_info: DeviceInfo,
// @SerialId(3) val str_info: String = "",
// @SerialId(4) val province: String,
@ -27,20 +27,20 @@ class Oidb0x769 {
@Serializable
class QueryUinPackageUsageReq(
@SerialId(1) val type: Int,
@SerialId(2) val uinFileSize: Long = 0
@ProtoId(1) val type: Int,
@ProtoId(2) val uinFileSize: Long = 0
): ProtoBuf
@Serializable
class ConfigSeq(
@SerialId(1) val type: Int, // uint
@SerialId(2) val version: Int // uint
@ProtoId(1) val type: Int, // uint
@ProtoId(2) val version: Int // uint
): ProtoBuf
@Serializable
class DeviceInfo(
@SerialId(1) val brand: String,
@SerialId(2) val model: String
@ProtoId(1) val brand: String,
@ProtoId(2) val model: String
//@SerialId(3) val os: OS,
//@SerialId(4) val cpu: CPU,
//@SerialId(5) val memory: Memory,
@ -51,45 +51,45 @@ class Oidb0x769 {
@Serializable
class OS(
@SerialId(1) val type: Int = 1,
@SerialId(2) val version: String,
@SerialId(3) val sdk: String,
@SerialId(4) val kernel: String,
@SerialId(5) val rom: String
@ProtoId(1) val type: Int = 1,
@ProtoId(2) val version: String,
@ProtoId(3) val sdk: String,
@ProtoId(4) val kernel: String,
@ProtoId(5) val rom: String
): ProtoBuf
@Serializable
class Camera(
@SerialId(1) val primary: Long,
@SerialId(2) val secondary: Long,
@SerialId(3) val flag: Boolean
@ProtoId(1) val primary: Long,
@ProtoId(2) val secondary: Long,
@ProtoId(3) val flag: Boolean
): ProtoBuf
@Serializable
class CPU(
@SerialId(1) val model: String,
@SerialId(2) val frequency: Int,
@SerialId(3) val cores: Int
@ProtoId(1) val model: String,
@ProtoId(2) val frequency: Int,
@ProtoId(3) val cores: Int
): ProtoBuf
@Serializable
class Memory(
@SerialId(1) val total: Int,
@SerialId(2) val process: Int
@ProtoId(1) val total: Int,
@ProtoId(2) val process: Int
): ProtoBuf
@Serializable
class Screen(
@SerialId(1) val model: String,
@SerialId(2) val width: Int,
@SerialId(3) val height: Int,
@SerialId(4) val dpi: Int,
@SerialId(5) val multiTouch: Boolean
@ProtoId(1) val model: String,
@ProtoId(2) val width: Int,
@ProtoId(3) val height: Int,
@ProtoId(4) val dpi: Int,
@ProtoId(5) val multiTouch: Boolean
): ProtoBuf
@Serializable
class Storage(
@SerialId(1) val builtin: Int,
@SerialId(2) val external: Int
@ProtoId(1) val builtin: Int,
@ProtoId(2) val external: Int
): ProtoBuf
}

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@ -18,11 +18,11 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
internal class MsgOnlinePush {
@Serializable
internal class PbPushMsg(
@SerialId(1) val msg: MsgComm.Msg,
@SerialId(2) val svrip: Int = 0,
@SerialId(3) val pushToken: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val pingFlag: Int = 0,
@SerialId(9) val generalFlag: Int = 0
@ProtoId(1) val msg: MsgComm.Msg,
@ProtoId(2) val svrip: Int = 0,
@ProtoId(3) val pushToken: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val pingFlag: Int = 0,
@ProtoId(9) val generalFlag: Int = 0
) : ProtoBuf
}
@ -30,24 +30,24 @@ internal class MsgOnlinePush {
class OnlinePushTrans : ProtoBuf {
@Serializable
class ExtGroupKeyInfo(
@SerialId(1) val curMaxSeq: Int = 0,
@SerialId(2) val curTime: Long = 0L
@ProtoId(1) val curMaxSeq: Int = 0,
@ProtoId(2) val curTime: Long = 0L
) : ProtoBuf
@Serializable
class PbMsgInfo(
@SerialId(1) val fromUin: Long = 0L,
@SerialId(2) val toUin: Long = 0L,
@SerialId(3) val msgType: Int = 0,
@SerialId(4) val msgSubtype: Int = 0,
@SerialId(5) val msgSeq: Int = 0,
@SerialId(6) val msgUid: Long = 0L,
@SerialId(7) val msgTime: Int = 0,
@SerialId(8) val realMsgTime: Int = 0,
@SerialId(9) val nickName: String = "",
@SerialId(10) val msgData: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val svrIp: Int = 0,
@SerialId(12) val extGroupKeyInfo: OnlinePushTrans.ExtGroupKeyInfo? = null,
@SerialId(17) val generalFlag: Int = 0
@ProtoId(1) val fromUin: Long = 0L,
@ProtoId(2) val toUin: Long = 0L,
@ProtoId(3) val msgType: Int = 0,
@ProtoId(4) val msgSubtype: Int = 0,
@ProtoId(5) val msgSeq: Int = 0,
@ProtoId(6) val msgUid: Long = 0L,
@ProtoId(7) val msgTime: Int = 0,
@ProtoId(8) val realMsgTime: Int = 0,
@ProtoId(9) val nickName: String = "",
@ProtoId(10) val msgData: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(11) val svrIp: Int = 0,
@ProtoId(12) val extGroupKeyInfo: OnlinePushTrans.ExtGroupKeyInfo? = null,
@ProtoId(17) val generalFlag: Int = 0
) : ProtoBuf
}

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@ -18,68 +18,68 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
class Generalflags : ProtoBuf {
@Serializable
class ResvAttr(
@SerialId(1) val globalGroupLevel: Int = 0,
@SerialId(2) val nearbyCharmLevel: Int = 0,
@SerialId(3) val redbagMsgSenderUin: Long = 0L,
@SerialId(4) val titleId: Int = 0,
@SerialId(5) val robotMsgFlag: Int = 0,
@SerialId(6) val wantGiftSenderUin: Long = 0L,
@SerialId(7) val stickerX: Float = 0.0f,
@SerialId(8) val stickerY: Float = 0.0f,
@SerialId(9) val stickerWidth: Float = 0.0f,
@SerialId(10) val stickerHeight: Float = 0.0f,
@SerialId(11) val stickerRotate: Int = 0,
@SerialId(12) val stickerHostMsgseq: Long = 0L,
@SerialId(13) val stickerHostMsguid: Long = 0L,
@SerialId(14) val stickerHostTime: Long = 0L,
@SerialId(15) val mobileCustomFont: Int = 0,
@SerialId(16) val tailKey: Int = 0,
@SerialId(17) val showTailFlag: Int = 0,
@SerialId(18) val doutuMsgType: Int = 0,
@SerialId(19) val doutuCombo: Int = 0,
@SerialId(20) val customFeatureid: Int = 0,
@SerialId(21) val goldenMsgType: Int = 0,
@SerialId(22) val goldenMsgInfo: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(23) val botMessageClassId: Int = 0,
@SerialId(24) val subscriptionUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(25) val pendantDiyId: Int = 0,
@SerialId(26) val timedMessage: Int = 0,
@SerialId(27) val holidayFlag: Int = 0,
@SerialId(29) val kplInfo: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(30) val faceId: Int = 0,
@SerialId(31) val diyFontTimestamp: Int = 0,
@SerialId(32) val redEnvelopeType: Int = 0,
@SerialId(33) val shortVideoId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(34) val reqFontEffectId: Int = 0,
@SerialId(35) val loveLanguageFlag: Int = 0,
@SerialId(36) val aioSyncToStoryFlag: Int = 0,
@SerialId(37) val uploadImageToQzoneFlag: Int = 0,
@SerialId(39) val uploadImageToQzoneParam: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(40) val groupConfessSig: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(41) val subfontId: Long = 0L,
@SerialId(42) val msgFlagType: Int = 0,
@SerialId(43) val uint32CustomFeatureid: List<Int>? = null,
@SerialId(44) val richCardNameVer: Int = 0,
@SerialId(47) val msgInfoFlag: Int = 0,
@SerialId(48) val serviceMsgType: Int = 0,
@SerialId(49) val serviceMsgRemindType: Int = 0,
@SerialId(50) val serviceMsgName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(51) val vipType: Int = 0,
@SerialId(52) val vipLevel: Int = 0,
@SerialId(53) val pbPttWaveform: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(54) val userBigclubLevel: Int = 0,
@SerialId(55) val userBigclubFlag: Int = 0,
@SerialId(56) val nameplate: Int = 0,
@SerialId(57) val autoReply: Int = 0,
@SerialId(58) val reqIsBigclubHidden: Int = 0,
@SerialId(59) val showInMsgList: Int = 0,
@SerialId(60) val oacMsgExtend: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(61) val groupMemberFlagEx2: Int = 0,
@SerialId(62) val groupRingtoneId: Int = 0,
@SerialId(63) val robotGeneralTrans: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(64) val troopPobingTemplate: Int = 0,
@SerialId(65) val hudongMark: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(66) val groupInfoFlagEx3: Int = 0
@ProtoId(1) val globalGroupLevel: Int = 0,
@ProtoId(2) val nearbyCharmLevel: Int = 0,
@ProtoId(3) val redbagMsgSenderUin: Long = 0L,
@ProtoId(4) val titleId: Int = 0,
@ProtoId(5) val robotMsgFlag: Int = 0,
@ProtoId(6) val wantGiftSenderUin: Long = 0L,
@ProtoId(7) val stickerX: Float = 0.0f,
@ProtoId(8) val stickerY: Float = 0.0f,
@ProtoId(9) val stickerWidth: Float = 0.0f,
@ProtoId(10) val stickerHeight: Float = 0.0f,
@ProtoId(11) val stickerRotate: Int = 0,
@ProtoId(12) val stickerHostMsgseq: Long = 0L,
@ProtoId(13) val stickerHostMsguid: Long = 0L,
@ProtoId(14) val stickerHostTime: Long = 0L,
@ProtoId(15) val mobileCustomFont: Int = 0,
@ProtoId(16) val tailKey: Int = 0,
@ProtoId(17) val showTailFlag: Int = 0,
@ProtoId(18) val doutuMsgType: Int = 0,
@ProtoId(19) val doutuCombo: Int = 0,
@ProtoId(20) val customFeatureid: Int = 0,
@ProtoId(21) val goldenMsgType: Int = 0,
@ProtoId(22) val goldenMsgInfo: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(23) val botMessageClassId: Int = 0,
@ProtoId(24) val subscriptionUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(25) val pendantDiyId: Int = 0,
@ProtoId(26) val timedMessage: Int = 0,
@ProtoId(27) val holidayFlag: Int = 0,
@ProtoId(29) val kplInfo: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(30) val faceId: Int = 0,
@ProtoId(31) val diyFontTimestamp: Int = 0,
@ProtoId(32) val redEnvelopeType: Int = 0,
@ProtoId(33) val shortVideoId: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(34) val reqFontEffectId: Int = 0,
@ProtoId(35) val loveLanguageFlag: Int = 0,
@ProtoId(36) val aioSyncToStoryFlag: Int = 0,
@ProtoId(37) val uploadImageToQzoneFlag: Int = 0,
@ProtoId(39) val uploadImageToQzoneParam: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(40) val groupConfessSig: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(41) val subfontId: Long = 0L,
@ProtoId(42) val msgFlagType: Int = 0,
@ProtoId(43) val uint32CustomFeatureid: List<Int>? = null,
@ProtoId(44) val richCardNameVer: Int = 0,
@ProtoId(47) val msgInfoFlag: Int = 0,
@ProtoId(48) val serviceMsgType: Int = 0,
@ProtoId(49) val serviceMsgRemindType: Int = 0,
@ProtoId(50) val serviceMsgName: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(51) val vipType: Int = 0,
@ProtoId(52) val vipLevel: Int = 0,
@ProtoId(53) val pbPttWaveform: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(54) val userBigclubLevel: Int = 0,
@ProtoId(55) val userBigclubFlag: Int = 0,
@ProtoId(56) val nameplate: Int = 0,
@ProtoId(57) val autoReply: Int = 0,
@ProtoId(58) val reqIsBigclubHidden: Int = 0,
@ProtoId(59) val showInMsgList: Int = 0,
@ProtoId(60) val oacMsgExtend: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(61) val groupMemberFlagEx2: Int = 0,
@ProtoId(62) val groupRingtoneId: Int = 0,
@ProtoId(63) val robotGeneralTrans: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(64) val troopPobingTemplate: Int = 0,
@ProtoId(65) val hudongMark: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(66) val groupInfoFlagEx3: Int = 0
) : ProtoBuf
}
@ -87,27 +87,27 @@ class Generalflags : ProtoBuf {
class ResvAttrForGiftMsg : ProtoBuf {
@Serializable
class ActivityGiftInfo(
@SerialId(1) val isActivityGift: Int = 0,
@SerialId(2) val textColor: String = "",
@SerialId(3) val text: String = "",
@SerialId(4) val url: String = ""
@ProtoId(1) val isActivityGift: Int = 0,
@ProtoId(2) val textColor: String = "",
@ProtoId(3) val text: String = "",
@ProtoId(4) val url: String = ""
) : ProtoBuf
@Serializable
class InteractGift(
@SerialId(1) val interactId: ByteArray = EMPTY_BYTE_ARRAY
@ProtoId(1) val interactId: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ResvAttr(
@SerialId(1) val int32SendScore: Int = 0,
@SerialId(2) val int32RecvScore: Int = 0,
@SerialId(3) val charmHeroism: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val buttonFlag: Int = 0,
@SerialId(5) val objColor: Int = 0,
@SerialId(6) val animationType: Int = 0,
@SerialId(7) val msgInteractGift: ResvAttrForGiftMsg.InteractGift? = null,
@SerialId(8) val activityGiftInfo: ResvAttrForGiftMsg.ActivityGiftInfo? = null
@ProtoId(1) val int32SendScore: Int = 0,
@ProtoId(2) val int32RecvScore: Int = 0,
@ProtoId(3) val charmHeroism: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val buttonFlag: Int = 0,
@ProtoId(5) val objColor: Int = 0,
@ProtoId(6) val animationType: Int = 0,
@ProtoId(7) val msgInteractGift: ResvAttrForGiftMsg.InteractGift? = null,
@ProtoId(8) val activityGiftInfo: ResvAttrForGiftMsg.ActivityGiftInfo? = null
) : ProtoBuf
}
@ -115,9 +115,9 @@ class ResvAttrForGiftMsg : ProtoBuf {
class SourceMsg : ProtoBuf {
@Serializable
class ResvAttr(
@SerialId(1) val richMsg2: ByteArray? = null,
@SerialId(2) val oriMsgtype: Int? = null,
@SerialId(3) val origUids: Long? = null // 原来是 list
@ProtoId(1) val richMsg2: ByteArray? = null,
@ProtoId(2) val oriMsgtype: Int? = null,
@ProtoId(3) val origUids: Long? = null // 原来是 list
) : ProtoBuf
}
@ -125,17 +125,17 @@ class SourceMsg : ProtoBuf {
class VideoFile : ProtoBuf {
@Serializable
class ResvAttr(
@SerialId(1) val hotvideoIcon: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val hotvideoTitle: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val hotvideoUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val hotvideoIconSub: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val specialVideoType: Int = 0,
@SerialId(6) val dynamicText: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val msgTailType: Int = 0,
@SerialId(8) val redEnvelopeType: Int = 0,
@SerialId(9) val shortVideoId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val animojiModelId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val longVideoKandianType: Int = 0,
@SerialId(12) val source: Int = 0
@ProtoId(1) val hotvideoIcon: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(2) val hotvideoTitle: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(3) val hotvideoUrl: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(4) val hotvideoIconSub: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(5) val specialVideoType: Int = 0,
@ProtoId(6) val dynamicText: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(7) val msgTailType: Int = 0,
@ProtoId(8) val redEnvelopeType: Int = 0,
@ProtoId(9) val shortVideoId: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(10) val animojiModelId: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(11) val longVideoKandianType: Int = 0,
@ProtoId(12) val source: Int = 0
) : ProtoBuf
}

View File

@ -9,30 +9,30 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
class StatSvcGetOnline {
@Serializable
class Instance(
@SerialId(1) val instanceId: Int = 0,
@SerialId(2) val clientType: Int = 0
@ProtoId(1) val instanceId: Int = 0,
@ProtoId(2) val clientType: Int = 0
) : ProtoBuf
@Serializable
class ReqBody(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val appid: Int = 0
@ProtoId(1) val uin: Long = 0L,
@ProtoId(2) val appid: Int = 0
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1) val errorCode: Int = 0,
@SerialId(2) val errorMsg: String = "",
@SerialId(3) val uin: Long = 0L,
@SerialId(4) val appid: Int = 0,
@SerialId(5) val timeInterval: Int = 0,
@SerialId(6) val msgInstances: List<StatSvcGetOnline.Instance>? = null
@ProtoId(1) val errorCode: Int = 0,
@ProtoId(2) val errorMsg: String = "",
@ProtoId(3) val uin: Long = 0L,
@ProtoId(4) val appid: Int = 0,
@ProtoId(5) val timeInterval: Int = 0,
@ProtoId(6) val msgInstances: List<StatSvcGetOnline.Instance>? = null
) : ProtoBuf
}

View File

@ -9,23 +9,23 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.proto
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import kotlin.math.absoluteValue
import kotlin.random.Random
@Serializable
class SyncCookie(
@SerialId(1) val time1: Long? = null, // 1580277992
@SerialId(2) val time: Long, // 1580277992
@SerialId(3) val unknown1: Long = Random.nextLong().absoluteValue,// 678328038
@SerialId(4) val unknown2: Long = Random.nextLong().absoluteValue, // 1687142153
@SerialId(5) val const1: Long = const1_, // 1458467940
@SerialId(11) val const2: Long = const2_, // 2683038258
@SerialId(12) val unknown3: Long = 0x1d,
@SerialId(13) val lastSyncTime: Long? = null,
@SerialId(14) val unknown4: Long = 0
@ProtoId(1) val time1: Long? = null, // 1580277992
@ProtoId(2) val time: Long, // 1580277992
@ProtoId(3) val unknown1: Long = Random.nextLong().absoluteValue,// 678328038
@ProtoId(4) val unknown2: Long = Random.nextLong().absoluteValue, // 1687142153
@ProtoId(5) val const1: Long = const1_, // 1458467940
@ProtoId(11) val const2: Long = const2_, // 2683038258
@ProtoId(12) val unknown3: Long = 0x1d,
@ProtoId(13) val lastSyncTime: Long? = null,
@ProtoId(14) val unknown4: Long = 0
) : ProtoBuf
private val const1_: Long = Random.nextLong().absoluteValue

View File

@ -9,14 +9,17 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet
import io.ktor.utils.io.core.*
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.buildPacket
import kotlinx.io.core.writeFully
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.utils.cryptor.ECDH
import net.mamoe.mirai.utils.cryptor.ECDHKeyPair
import net.mamoe.mirai.utils.io.encryptAndWrite
import net.mamoe.mirai.utils.io.writeShortLVByteArray
@UseExperimental(ExperimentalUnsignedTypes::class)
@OptIn(ExperimentalUnsignedTypes::class)
internal interface EncryptMethod {
val id: Int

View File

@ -10,7 +10,10 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet
import io.ktor.utils.io.core.*
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.buildPacket
import kotlinx.io.core.writeFully
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.io.encryptAndWrite
@ -31,7 +34,7 @@ internal class OutgoingPacket constructor(
internal val KEY_16_ZEROS = ByteArray(16)
internal val EMPTY_BYTE_ARRAY = ByteArray(0)
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal inline fun OutgoingPacketFactory<*>.buildOutgoingUniPacket(
client: QQAndroidClient,
bodyType: Byte = 1, // 1: PB?
@ -43,7 +46,6 @@ internal inline fun OutgoingPacketFactory<*>.buildOutgoingUniPacket(
body: BytePacketBuilder.(sequenceId: Int) -> Unit
): OutgoingPacket {
@Suppress("DuplicatedCode")
return OutgoingPacket(name, commandName, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x0B)
@ -52,7 +54,7 @@ internal inline fun OutgoingPacketFactory<*>.buildOutgoingUniPacket(
writeByte(0)
client.uin.toString().let {
writeInt(it.length + 4)
writeText(it)
writeStringUtf8(it)
}
encryptAndWrite(key) {
writeUniPacket(commandName, client.outgoingPacketSessionId, extraData) {
@ -64,7 +66,7 @@ internal inline fun OutgoingPacketFactory<*>.buildOutgoingUniPacket(
}
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal inline fun IncomingPacketFactory<*>.buildResponseUniPacket(
client: QQAndroidClient,
bodyType: Byte = 1, // 1: PB?
@ -75,7 +77,6 @@ internal inline fun IncomingPacketFactory<*>.buildResponseUniPacket(
sequenceId: Int = client.nextSsoSequenceId(),
body: BytePacketBuilder.(sequenceId: Int) -> Unit
): OutgoingPacket {
@Suppress("DuplicatedCode")
return OutgoingPacket(name, commandName, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x0B)
@ -84,7 +85,7 @@ internal inline fun IncomingPacketFactory<*>.buildResponseUniPacket(
writeByte(0)
client.uin.toString().let {
writeInt(it.length + 4)
writeText(it)
writeStringUtf8(it)
}
encryptAndWrite(key) {
writeUniPacket(commandName, client.outgoingPacketSessionId, extraData) {
@ -95,7 +96,7 @@ internal inline fun IncomingPacketFactory<*>.buildResponseUniPacket(
})
}
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal inline fun BytePacketBuilder.writeUniPacket(
commandName: String,
unknownData: ByteArray,
@ -105,7 +106,7 @@ internal inline fun BytePacketBuilder.writeUniPacket(
writeIntLVPacket(lengthOffset = { it + 4 }) {
commandName.let {
writeInt(it.length + 4)
writeText(it)
writeStringUtf8(it)
}
writeInt(4 + 4)
@ -128,7 +129,7 @@ internal val NO_ENCRYPT: ByteArray = ByteArray(0)
/**
* com.tencent.qphone.base.util.CodecWarpper#encodeRequest(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int, int, java.lang.String, byte, byte, byte, byte[], byte[], boolean)
*/
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal inline fun OutgoingPacketFactory<*>.buildLoginOutgoingPacket(
client: QQAndroidClient,
bodyType: Byte,
@ -152,7 +153,7 @@ internal inline fun OutgoingPacketFactory<*>.buildLoginOutgoingPacket(
client.uin.toString().let {
writeInt(it.length + 4)
writeText(it)
writeStringUtf8(it)
}
if (key === NO_ENCRYPT) {
@ -166,7 +167,7 @@ internal inline fun OutgoingPacketFactory<*>.buildLoginOutgoingPacket(
private inline val BRP_STUB get() = ByteReadPacket.Empty
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal inline fun BytePacketBuilder.writeSsoPacket(
client: QQAndroidClient,
subAppId: Long,
@ -207,7 +208,7 @@ internal inline fun BytePacketBuilder.writeSsoPacket(
}
commandName.let {
writeInt(it.length + 4)
writeText(it)
writeStringUtf8(it)
}
writeInt(4 + 4)
@ -215,7 +216,7 @@ internal inline fun BytePacketBuilder.writeSsoPacket(
client.device.imei.let {
writeInt(it.length + 4)
writeText(it)
writeStringUtf8(it)
}
writeInt(4)
@ -232,7 +233,7 @@ internal inline fun BytePacketBuilder.writeSsoPacket(
writeIntLVPacket(lengthOffset = { it + 4 }, builder = body)
}
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
@OptIn(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
internal fun BytePacketBuilder.writeOicqRequestPacket(
client: QQAndroidClient,
encryptMethod: EncryptMethod,

View File

@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet
import io.ktor.utils.io.core.*
import io.ktor.utils.io.pool.useInstance
import kotlinx.io.core.*
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.qqandroid.QQAndroidBot
@ -48,7 +48,7 @@ internal sealed class PacketFactory<TPacket : Packet?> {
*
* @param TPacket 服务器回复包解析结果
*/
@UseExperimental(ExperimentalUnsignedTypes::class)
@OptIn(ExperimentalUnsignedTypes::class)
internal abstract class OutgoingPacketFactory<TPacket : Packet?>(
/**
* 命令名. `wtlogin.login`, `ConfigPushSvc.PushDomain`
@ -97,10 +97,15 @@ internal abstract class IncomingPacketFactory<TPacket : Packet?>(
}
@JvmName("decode0")
private suspend inline fun <P : Packet?> OutgoingPacketFactory<P>.decode(bot: QQAndroidBot, packet: ByteReadPacket): P = packet.decode(bot)
private suspend inline fun <P : Packet?> OutgoingPacketFactory<P>.decode(bot: QQAndroidBot, packet: ByteReadPacket): P =
packet.decode(bot)
@JvmName("decode1")
private suspend inline fun <P : Packet?> IncomingPacketFactory<P>.decode(bot: QQAndroidBot, packet: ByteReadPacket, sequenceId: Int): P =
private suspend inline fun <P : Packet?> IncomingPacketFactory<P>.decode(
bot: QQAndroidBot,
packet: ByteReadPacket,
sequenceId: Int
): P =
packet.decode(bot, sequenceId)
internal val DECRYPTER_16_ZERO = ByteArray(16)
@ -117,7 +122,7 @@ internal val PacketLogger: MiraiLoggerWithSwitch = DefaultLogger("Packet").withS
/**
* 已知的数据包工厂列表.
*/
@UseExperimental(ExperimentalUnsignedTypes::class)
@OptIn(ExperimentalUnsignedTypes::class)
internal object KnownPacketFactories {
object OutgoingFactories : List<OutgoingPacketFactory<*>> by mutableListOf(
WtLogin.Login,
@ -164,74 +169,91 @@ internal object KnownPacketFactories {
* full packet without length
*/
// do not inline. Exceptions thrown will not be reported correctly
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
@Suppress("UNCHECKED_CAST")
suspend fun <T : Packet?> parseIncomingPacket(bot: QQAndroidBot, rawInput: Input, consumer: PacketConsumer<T>) = with(rawInput) {
// login
val flag1 = readInt()
suspend fun <T : Packet?> parseIncomingPacket(bot: QQAndroidBot, rawInput: Input, consumer: PacketConsumer<T>) =
with(rawInput) {
// login
val flag1 = readInt()
PacketLogger.verbose { "开始处理一个包" }
PacketLogger.verbose { "flag1(0A/0B) = ${flag1.toUByte().toUHexString()}" }
PacketLogger.verbose { "开始处理一个包" }
PacketLogger.verbose { "flag1(0A/0B) = ${flag1.toUByte().toUHexString()}" }
val flag2 = readByte().toInt()
PacketLogger.verbose {
"包类型(flag2) = $flag2. (可能是 ${when (flag2) {
2 -> "OicqRequest"
1 -> "Uni/ProtoBuf"
0 -> "Heartbeat"
else -> "未知"
}})"
}
val flag2 = readByte().toInt()
PacketLogger.verbose {
"包类型(flag2) = $flag2. (可能是 ${when (flag2) {
2 -> "OicqRequest"
1 -> "Uni/ProtoBuf"
0 -> "Heartbeat"
else -> "未知"
}})"
}
val flag3 = readByte().toInt()
check(flag3 == 0) { "Illegal flag3. Expected 0, whereas got $flag3. flag1=$flag1, flag2=$flag2. Remaining=${this.readBytes().toUHexString()}" }
val flag3 = readByte().toInt()
check(flag3 == 0) {
"Illegal flag3. Expected 0, whereas got $flag3. flag1=$flag1, flag2=$flag2. Remaining=${this.readBytes()
.toUHexString()}"
}
readString(readInt() - 4)// uinAccount
readString(readInt() - 4)// uinAccount
ByteArrayPool.useInstance { data ->
val size = this.readAvailable(data)
ByteArrayPool.useInstance { data ->
val size = this.readAvailable(data)
kotlin.runCatching {
when (flag2) {
2 -> TEA.decrypt(data, DECRYPTER_16_ZERO, size).also { PacketLogger.verbose { "成功使用 16 zero 解密" } }
1 -> TEA.decrypt(data, bot.client.wLoginSigInfo.d2Key, size).also { PacketLogger.verbose { "成功使用 d2Key 解密" } }
0 -> data
else -> error("")
kotlin.runCatching {
when (flag2) {
2 -> TEA.decrypt(data, DECRYPTER_16_ZERO, size)
.also { PacketLogger.verbose { "成功使用 16 zero 解密" } }
1 -> TEA.decrypt(data, bot.client.wLoginSigInfo.d2Key, size)
.also { PacketLogger.verbose { "成功使用 d2Key 解密" } }
0 -> data
else -> error("")
}
}.getOrElse {
PacketLogger.verbose { "失败, 尝试其他各种key" }
bot.client.tryDecryptOrNull(data, size) { it }
}?.toReadPacket()?.let { decryptedData ->
when (flag1) {
0x0A -> parseSsoFrame(bot, decryptedData)
0x0B -> parseSsoFrame(bot, decryptedData) // 这里可能是 uni?? 但测试时候发现结构跟 sso 一样.
else -> error("unknown flag1: ${flag1.toByte().toUHexString()}")
}
}?.let {
it as IncomingPacket<T>
if (it.packetFactory is IncomingPacketFactory<T> && bot.network.pendingEnabled) {
bot.network.pendingIncomingPackets?.addLast(it.also {
it.consumer = consumer
it.flag2 = flag2
PacketLogger.info { "Cached ${it.commandName} #${it.sequenceId}" }
}) ?: handleIncomingPacket(it, bot, flag2, consumer)
} else {
handleIncomingPacket(it, bot, flag2, consumer)
}
} ?: inline {
PacketLogger.error { "任何key都无法解密: ${data.take(size).toUHexString()}" }
return
}
}.getOrElse {
PacketLogger.verbose { "失败, 尝试其他各种key" }
bot.client.tryDecryptOrNull(data, size) { it }
}?.toReadPacket()?.let { decryptedData ->
when (flag1) {
0x0A -> parseSsoFrame(bot, decryptedData)
0x0B -> parseSsoFrame(bot, decryptedData) // 这里可能是 uni?? 但测试时候发现结构跟 sso 一样.
else -> error("unknown flag1: ${flag1.toByte().toUHexString()}")
}
}?.let {
it as IncomingPacket<T>
if (it.packetFactory is IncomingPacketFactory<T> && bot.network.pendingEnabled) {
bot.network.pendingIncomingPackets?.addLast(it.also {
it.consumer = consumer
it.flag2 = flag2
PacketLogger.info { "Cached ${it.commandName} #${it.sequenceId}" }
}) ?: handleIncomingPacket(it, bot, flag2, consumer)
} else {
handleIncomingPacket(it, bot, flag2, consumer)
}
} ?: inline {
PacketLogger.error { "任何key都无法解密: ${data.take(size).toUHexString()}" }
return
}
}
}
@UseExperimental(MiraiInternalAPI::class)
internal suspend fun <T : Packet?> handleIncomingPacket(it: IncomingPacket<T>, bot: QQAndroidBot, flag2: Int, consumer: PacketConsumer<T>) {
@OptIn(MiraiInternalAPI::class)
internal suspend fun <T : Packet?> handleIncomingPacket(
it: IncomingPacket<T>,
bot: QQAndroidBot,
flag2: Int,
consumer: PacketConsumer<T>
) {
if (it.packetFactory == null) {
bot.network.logger.debug("Received commandName: ${it.commandName}")
PacketLogger.warning { "找不到 PacketFactory" }
PacketLogger.verbose { "传递给 PacketFactory 的数据 = ${it.data.useBytes { data, length -> data.toUHexString(length = length) }}" }
PacketLogger.verbose {
"传递给 PacketFactory 的数据 = ${it.data.useBytes { data, length ->
data.toUHexString(
length = length
)
}}"
}
return
}
@ -254,8 +276,15 @@ internal object KnownPacketFactories {
)
}
2 -> it.data.parseOicqResponse(bot, it.packetFactory as OutgoingPacketFactory<T>, it.sequenceId, consumer)
else -> error("unknown flag2: $flag2. Body to be parsed for inner packet=${it.data.readBytes().toUHexString()}")
2 -> it.data.parseOicqResponse(
bot,
it.packetFactory as OutgoingPacketFactory<T>,
it.sequenceId,
consumer
)
else -> error(
"unknown flag2: $flag2. Body to be parsed for inner packet=${it.data.readBytes().toUHexString()}"
)
}
}
}
@ -275,7 +304,7 @@ internal object KnownPacketFactories {
/**
* 解析 SSO 层包装
*/
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
@OptIn(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
private fun parseSsoFrame(bot: QQAndroidBot, input: ByteReadPacket): IncomingPacket<*> {
val commandName: String
val ssoSequenceId: Int
@ -313,7 +342,7 @@ internal object KnownPacketFactories {
1 -> {
input.discardExact(4)
input.useBytes { data, length ->
data.unzip(length = length).let {
MiraiPlatformUtils.unzip(data, 0, length).let {
val size = it.toInt()
if (size == it.size || size == it.size + 4) {
it.toReadPacket(offset = 4)
@ -336,7 +365,7 @@ internal object KnownPacketFactories {
return IncomingPacket(packetFactory, ssoSequenceId, packet, commandName)
}
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
private suspend fun <T : Packet?> ByteReadPacket.parseOicqResponse(
bot: QQAndroidBot,
packetFactory: OutgoingPacketFactory<T>,
@ -357,7 +386,8 @@ internal object KnownPacketFactories {
4 -> {
var data = TEA.decrypt(this, bot.client.ecdh.keyPair.initialShareKey, (this.remaining - 1).toInt())
val peerShareKey = bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey())
val peerShareKey =
bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey())
data = TEA.decrypt(data, peerShareKey)
packetFactory.decode(bot, data)

View File

@ -9,12 +9,16 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet
import io.ktor.utils.io.core.*
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.toByteArray
import kotlinx.io.core.writeFully
import net.mamoe.mirai.qqandroid.network.protocol.LoginType
import net.mamoe.mirai.qqandroid.utils.NetworkType
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.MiraiPlatformUtils
import net.mamoe.mirai.utils.currentTimeMillis
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.md5
import kotlin.random.Random
/**
@ -73,6 +77,7 @@ fun BytePacketBuilder.t18(
} shouldEqualsTo 22
}
@OptIn(MiraiInternalAPI::class)
fun BytePacketBuilder.t106(
appId: Long = 16L,
subAppId: Long = 537062845L,
@ -93,7 +98,7 @@ fun BytePacketBuilder.t106(
guid?.requireSize(16)
writeShortLVPacket {
encryptAndWrite(md5(passwordMd5 + ByteArray(4) + (salt.takeIf { it != 0L } ?: uin).toInt().toByteArray())) {
encryptAndWrite(MiraiPlatformUtils.md5(passwordMd5 + ByteArray(4) + (salt.takeIf { it != 0L } ?: uin).toInt().toByteArray())) {
writeShort(4)//TGTGTVer
writeInt(Random.nextInt())
writeInt(5)//ssoVer
@ -318,12 +323,13 @@ fun BytePacketBuilder.t144(
}
}
@OptIn(MiraiInternalAPI::class)
fun BytePacketBuilder.t109(
androidId: ByteArray
) {
writeShort(0x109)
writeShortLVPacket {
writeFully(md5(androidId))
writeFully(MiraiPlatformUtils.md5(androidId))
} shouldEqualsTo 16
}
@ -553,21 +559,23 @@ fun BytePacketBuilder.t400(
}
}
@OptIn(MiraiInternalAPI::class)
fun BytePacketBuilder.t187(
macAddress: ByteArray
) {
writeShort(0x187)
writeShortLVPacket {
writeFully(md5(macAddress)) // may be md5
writeFully(MiraiPlatformUtils.md5(macAddress)) // may be md5
}
}
@OptIn(MiraiInternalAPI::class)
fun BytePacketBuilder.t188(
androidId: ByteArray
) {
writeShort(0x188)
writeShortLVPacket {
writeFully(md5(androidId))
writeFully(MiraiPlatformUtils.md5(androidId))
} shouldEqualsTo 16
}

View File

@ -9,7 +9,7 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf

View File

@ -9,7 +9,10 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat
import io.ktor.utils.io.core.*
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.buildPacket
import kotlinx.io.core.readBytes
import kotlinx.io.core.toByteArray
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.data.Packet
@ -375,7 +378,7 @@ internal class TroopManagement {
OutgoingPacketFactory<EditGroupNametag.Response>("friendlist.ModifyGroupCardReq") {
object Response : Packet
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): EditGroupNametag.Response {
return Response
}

View File

@ -9,7 +9,7 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf

View File

@ -9,7 +9,7 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf

View File

@ -9,9 +9,10 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.*
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.data.MemberInfo
@ -74,7 +75,7 @@ internal class MessageSvc {
/**
* 获取好友消息和消息记录
*/
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal object PbGetMsg : OutgoingPacketFactory<PbGetMsg.Response>("MessageSvc.PbGetMsg") {
operator fun invoke(
client: QQAndroidClient,
@ -105,7 +106,7 @@ internal class MessageSvc {
)
}
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
open class GetMsgSuccess(delegate: List<Packet>) : Response(MsgSvc.SyncFlag.STOP, delegate) {
override fun toString(): String = "MessageSvc.PbGetMsg.GetMsgSuccess(messages=<Iterable>))"
}
@ -122,7 +123,7 @@ internal class MessageSvc {
object EmptyResponse : GetMsgSuccess(emptyList())
@UseExperimental(MiraiInternalAPI::class, MiraiExperimentalAPI::class, FlowPreview::class)
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class, FlowPreview::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
// 00 00 01 0F 08 00 12 00 1A 34 08 FF C1 C4 F1 05 10 FF C1 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 8A CA 91 D1 0C 48 9B A5 BD 9B 0A 58 DE 9D 99 F8 08 60 1D 68 FF C1 C4 F1 05 70 00 20 02 2A 9D 01 08 F3 C1 C4 F1 05 10 A2 FF 8C F0 03 18 01 22 8A 01 0A 2A 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 A6 01 20 0B 28 AE F9 01 30 F4 C1 C4 F1 05 38 A7 E3 D8 D4 84 80 80 80 01 B8 01 CD B5 01 12 08 08 01 10 00 18 00 20 00 1A 52 0A 50 0A 27 08 00 10 F4 C1 C4 F1 05 18 A7 E3 D8 D4 04 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 08 0A 06 0A 04 4E 4D 53 4C 12 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 12 04 4A 02 08 00 30 01 2A 15 08 97 A2 C1 F1 05 10 95 A6 F5 E5 0C 18 01 30 01 40 01 48 81 01 2A 10 08 D3 F7 B5 F1 05 10 DD F1 92 B7 07 18 01 30 01 38 00 42 00 48 00
val resp = readProtoBuf(MsgSvc.PbGetMsgResp.serializer())

View File

@ -11,7 +11,7 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import io.ktor.utils.io.core.*
import kotlinx.io.core.*
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.data.MultiPacketBySequence
import net.mamoe.mirai.data.NoPacket
@ -55,7 +55,7 @@ internal class OnlinePush {
}
}
@UseExperimental(ExperimentalStdlibApi::class)
@OptIn(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
if (!bot.firstLoginSucceed) return null
@ -94,7 +94,7 @@ internal class OnlinePush {
internal object PbPushTransMsg : IncomingPacketFactory<Packet>("OnlinePush.PbPushTransMsg", "OnlinePush.RespPush") {
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
@ExperimentalUnsignedTypes
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet {
val content = this.readProtoBuf(OnlinePushTrans.PbMsgInfo.serializer())
@ -187,7 +187,7 @@ internal class OnlinePush {
//0C 01 B1 89 BE 09 5E 3D 72 A6 00 01 73 68 FC 06 00 00 00 3C
internal object ReqPush : IncomingPacketFactory<Packet>("OnlinePush.ReqPush", "OnlinePush.RespPush") {
@ExperimentalUnsignedTypes
@UseExperimental(ExperimentalStdlibApi::class)
@OptIn(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet {
val reqPushMsg = decodeUniPacket(OnlinePushPack.SvcReqPushMsg.serializer(), "req")
@ -341,7 +341,7 @@ internal class OnlinePush {
}
}
0x11 -> {
discard(1)
discardExact(1)
val proto = readProtoBuf(TroopTips0x857.NotifyMsgBody.serializer())
proto.optMsgRecall?.let { recallReminder ->

View File

@ -9,7 +9,7 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.list
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket
@ -123,7 +123,8 @@ internal class FriendList {
}
}
internal object GetFriendGroupList : OutgoingPacketFactory<GetFriendGroupList.Response>("friendlist.getFriendGroupList") {
internal object GetFriendGroupList :
OutgoingPacketFactory<GetFriendGroupList.Response>("friendlist.getFriendGroupList") {
class Response(
val totalFriendCount: Short,

View File

@ -9,7 +9,7 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.JceCharset
import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket

View File

@ -9,7 +9,7 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.QQAndroidClient

View File

@ -9,23 +9,24 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.*
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.SvcReqRegister
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Oidb0x769
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.StatSvcGetOnline
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
import net.mamoe.mirai.qqandroid.utils.NetworkType
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.MiraiPlatformUtils
import net.mamoe.mirai.utils.io.encodeToString
import net.mamoe.mirai.utils.io.toReadPacket
import net.mamoe.mirai.utils.localIpAddress
@Suppress("EnumEntryName")
internal enum class RegPushReason {
@ -89,6 +90,7 @@ internal class StatSvc {
private const val subAppId = 537062845L
@OptIn(MiraiInternalAPI::class)
operator fun invoke(
client: QQAndroidClient,
regPushReason: RegPushReason = RegPushReason.appRegister
@ -138,7 +140,7 @@ internal class StatSvc {
strOSVer = client.device.version.release.encodeToString(),
uOldSSOIp = 0,
uNewSSOIp = localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String ->
uNewSSOIp = MiraiPlatformUtils.localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String ->
acc or ((s.toLong() shl (index * 16)))
},
strVendorName = "MIUI",

View File

@ -11,7 +11,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import io.ktor.util.InternalAPI
import io.ktor.utils.io.core.*
import kotlinx.io.core.*
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.*
@ -29,7 +29,7 @@ internal class WtLogin {
* OicqRequest
*/
@Suppress("FunctionName")
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
@OptIn(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
internal object Login : OutgoingPacketFactory<Login.LoginPacketResponse>("wtlogin.login") {
private const val subAppId = 537062845L
@ -84,7 +84,7 @@ internal class WtLogin {
t8(2052)
t104(client.t104)
t116(150470524, 66560)
t401(md5(client.device.guid + "stMNokHgxZUGhsYp".toByteArray() + t402))
t401(MiraiPlatformUtils.md5(client.device.guid + "stMNokHgxZUGhsYp".toByteArray() + t402))
}
}
}
@ -127,7 +127,7 @@ internal class WtLogin {
private const val appId = 16L
private const val subAppId = 537062845L
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
operator fun invoke(
client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId ->
@ -309,7 +309,7 @@ internal class WtLogin {
}
@InternalAPI
@UseExperimental(MiraiDebugAPI::class)
@OptIn(MiraiDebugAPI::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): LoginPacketResponse {
discardExact(2) // subCommand
@ -355,7 +355,7 @@ internal class WtLogin {
val otherInfo: String = readUShortLVString()
LoginPacketResponse.Error(title, content, otherInfo)
} ?: tlvMap[0x146]?.toReadPacket()?.run {
} ?: tlvMap[0x146]?.read {
discardExact(2) // ver
discardExact(2) // code
@ -368,7 +368,7 @@ internal class WtLogin {
}
@InternalAPI
@UseExperimental(MiraiDebugAPI::class)
@OptIn(MiraiDebugAPI::class)
private fun onSolveLoginCaptcha(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse.Captcha {
/*
java.lang.IllegalStateException: UNKNOWN CAPTCHA QUESTION:
@ -404,7 +404,7 @@ internal class WtLogin {
error("UNKNOWN CAPTCHA, tlvMap=" + tlvMap._miraiContentToString())
}
@UseExperimental(MiraiDebugAPI::class)
@OptIn(MiraiDebugAPI::class)
private fun onLoginSuccess(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse.Success {
val client = bot.client
//println("TLV KEYS: " + tlvMap.keys.joinToString { it.contentToString() })

View File

@ -1,28 +0,0 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.command
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.network.protocol.packet.MessageMicro
/**
* oidb_cmd0xcf8$GetPublicAccountDetailInfoRequest
*/
@Serializable
class GetPublicAccountDetailInfoRequest(
val seqno: Int, // uint
val uinLong: Long,
val version: Int, // uint
val versionInfo: String
) : MessageMicro
class GetPublicAccountDetailInfoResponse(
) : MessageMicro

View File

@ -1,31 +0,0 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.sso
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.network.protocol.packet.MessageMicro
/**
* oidb_sso$OIDBSSOPkg
*/
@Serializable
class OidbSsoPackage(
@SerialId(1) val command: Int, // uint
@SerialId(2) val serviceType: Int, // uint
@SerialId(3) val result: Int, // uint
@SerialId(4) val bodyBuffer: ByteArray,
@SerialId(5) val errorMessage: String,
@SerialId(6) val clientVersion: String
) : MessageMicro

View File

@ -21,7 +21,7 @@ import kotlin.jvm.JvmName
/**
* Inline the block
*/
@UseExperimental(ExperimentalContracts::class)
@OptIn(ExperimentalContracts::class)
@PublishedApi
internal inline fun <R> inline(block: () -> R): R {
contract {

View File

@ -0,0 +1,471 @@
@file:Suppress("unused", "DEPRECATION_ERROR")
package net.mamoe.mirai.qqandroid.io.serialization
import kotlinx.io.core.buildPacket
import kotlinx.io.core.toByteArray
import kotlinx.io.core.writeFully
import kotlinx.serialization.MissingFieldException
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceInput
import net.mamoe.mirai.qqandroid.io.serialization.jce.writeJceHead
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
internal const val BYTE: Byte = 0
internal const val DOUBLE: Byte = 5
internal const val FLOAT: Byte = 4
internal const val INT: Byte = 2
internal const val JCE_MAX_STRING_LENGTH = 104857600
internal const val LIST: Byte = 9
internal const val LONG: Byte = 3
internal const val MAP: Byte = 8
internal const val SHORT: Byte = 1
internal const val SIMPLE_LIST: Byte = 13
internal const val STRING1: Byte = 6
internal const val STRING4: Byte = 7
internal const val STRUCT_BEGIN: Byte = 10
internal const val STRUCT_END: Byte = 11
internal const val ZERO_TYPE: Byte = 12
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@Suppress("INVISIBLE_MEMBER") // bug
internal class JceInputTest {
@Test
fun testFuckingComprehensiveStruct() {
@Serializable
data class TestSerializableClassC(
@JceId(5) val value3: Int = 123123
)
@Serializable
data class TestSerializableClassB(
@JceId(0) val value: Int,
@JceId(123) val nested2: TestSerializableClassC,
@JceId(5) val value5: Int
)
@Serializable
data class TestSerializableClassA(
@JceId(0) val map: Map<TestSerializableClassB, TestSerializableClassC>
)
val input = buildPacket {
writeJceHead(MAP, 0) // TestSerializableClassB
writeJceHead(BYTE, 0)
writeByte(1)
writeJceHead(STRUCT_BEGIN, 0);
{
writeJceHead(INT, 0)
writeInt(123)
writeJceHead(STRUCT_BEGIN, 123); // TestSerializableClassC
{
writeJceHead(INT, 5)
writeInt(123123)
}()
writeJceHead(STRUCT_END, 0)
writeJceHead(INT, 5)
writeInt(9)
}()
writeJceHead(STRUCT_END, 0)
writeJceHead(STRUCT_BEGIN, 1);
{
writeJceHead(INT, 5)
writeInt(123123)
}()
writeJceHead(STRUCT_END, 0)
}
assertEquals(
TestSerializableClassA(
mapOf(
TestSerializableClassB(123, TestSerializableClassC(123123), 9)
to TestSerializableClassC(123123)
)
),
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
@Test
fun testNestedJceStruct() {
@Serializable
data class TestSerializableClassC(
@JceId(5) val value3: Int
)
@Serializable
data class TestSerializableClassB(
@JceId(0) val value: Int,
@JceId(123) val nested2: TestSerializableClassC,
@JceId(5) val value5: Int
)
@Serializable
data class TestSerializableClassA(
@JceId(0) val value1: Int,
@JceId(4) val notOptional: Int,
@JceId(1) val nestedStruct: TestSerializableClassB,
@JceId(2) val optional: Int = 3
)
val input = buildPacket {
writeJceHead(INT, 0)
writeInt(444)
writeJceHead(STRUCT_BEGIN, 1); // TestSerializableClassB
{
writeJceHead(INT, 0)
writeInt(123)
writeJceHead(STRUCT_BEGIN, 123); // TestSerializableClassC
{
writeJceHead(INT, 5)
writeInt(123123)
}()
writeJceHead(STRUCT_END, 0)
writeJceHead(INT, 5)
writeInt(9)
}()
writeJceHead(STRUCT_END, 0)
writeJceHead(INT, 4)
writeInt(5)
}
assertEquals(
TestSerializableClassA(
444,
5,
TestSerializableClassB(123, TestSerializableClassC(123123), 9)
),
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
@Test
fun testNestedList() {
@Serializable
data class TestSerializableClassA(
// @JceId(0) val byteArray: ByteArray = byteArrayOf(1, 2, 3),
@JceId(3) val byteArray2: List<List<Int>> = listOf(listOf(1, 2, 3, 4), listOf(1, 2, 3, 4))
)
val input = buildPacket {
//writeJceHead(SIMPLE_LIST, 0)
//writeJceHead(BYTE, 0)
//writeJceHead(BYTE, 0)
//byteArrayOf(1, 2, 3).let {
// writeByte(it.size.toByte())
// writeFully(it)
//}
writeJceHead(LIST, 3)
writeJceHead(BYTE, 0)
writeByte(2)
listOf(listOf(1, 2, 3, 4), listOf(1, 2, 3, 4)).forEach { child ->
writeJceHead(LIST, 0)
writeJceHead(BYTE, 0)
writeByte(child.size.toByte())
child.forEach {
writeJceHead(INT, 0)
writeInt(it)
}
}
}
assertEquals(TestSerializableClassA(), Jce.UTF_8.load(TestSerializableClassA.serializer(), input))
}
@Test
fun testMap() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byteArray: Map<Int, Int>
)
val input = buildPacket {
writeJceHead(MAP, 0)
mapOf(1 to 2, 33 to 44).let {
writeJceHead(BYTE, 0)
writeByte(it.size.toByte())
it.forEach { (key, value) ->
writeJceHead(INT, 0)
writeInt(key)
writeJceHead(INT, 1)
writeInt(value)
}
}
writeJceHead(SIMPLE_LIST, 3)
writeJceHead(BYTE, 0)
byteArrayOf(1, 2, 3, 4).let {
writeJceHead(BYTE, 0)
writeByte(it.size.toByte())
writeFully(it)
}
}
assertEquals(
TestSerializableClassA(mapOf(1 to 2, 33 to 44)),
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
@Test
fun testMapStringInt() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byteArray: Map<String, Int>
)
val input = buildPacket {
writeJceHead(MAP, 0)
mapOf("str1" to 2, "str2" to 44).let {
writeJceHead(BYTE, 0)
writeByte(it.size.toByte())
it.forEach { (key, value) ->
writeJceHead(STRING1, 0)
writeByte(key.length.toByte())
writeStringUtf8(key)
writeJceHead(INT, 1)
writeInt(value)
}
}
}
assertEquals(
TestSerializableClassA(mapOf("str1" to 2, "str2" to 44)),
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
@Test
fun testMapStringByteArray() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val map: Map<String, ByteArray>
) {
override fun toString(): String {
@Suppress("EXPERIMENTAL_API_USAGE")
return map.entries.joinToString { "${it.key}=${it.value.contentToString()}" }
}
}
val input = buildPacket {
writeJceHead(MAP, 0)
mapOf("str1" to byteArrayOf(2, 3, 4), "str2" to byteArrayOf(2, 3, 4)).let {
writeJceHead(BYTE, 0)
writeByte(it.size.toByte())
it.forEach { (key, value) ->
writeJceHead(STRING1, 0)
writeByte(key.length.toByte())
writeFully(key.toByteArray())
writeJceHead(SIMPLE_LIST, 1)
writeJceHead(BYTE, 0)
writeJceHead(INT, 0)
writeInt(value.size)
writeFully(value)
}
}
}
assertEquals(
TestSerializableClassA(mapOf("str1" to byteArrayOf(2, 3, 4), "str2" to byteArrayOf(2, 3, 4))).toString(),
Jce.UTF_8.load(TestSerializableClassA.serializer(), input).toString()
)
}
@Test
fun testSimpleByteArray() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byteArray: ByteArray = byteArrayOf(1, 2, 3),
@JceId(3) val byteArray2: List<Byte> = listOf(1, 2, 3, 4)
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as TestSerializableClassA
if (!byteArray.contentEquals(other.byteArray)) return false
if (byteArray2 != other.byteArray2) return false
return true
}
override fun hashCode(): Int {
var result = byteArray.contentHashCode()
result = 31 * result + byteArray2.hashCode()
return result
}
}
val input = buildPacket {
writeJceHead(SIMPLE_LIST, 0)
writeJceHead(BYTE, 0)
byteArrayOf(1, 2, 3).let {
writeJceHead(BYTE, 0)
writeByte(it.size.toByte())
writeFully(it)
}
writeJceHead(SIMPLE_LIST, 3)
writeJceHead(BYTE, 0)
byteArrayOf(1, 2, 3, 4).let {
writeJceHead(BYTE, 0)
writeByte(it.size.toByte())
writeFully(it)
}
}
assertEquals(TestSerializableClassA(), Jce.UTF_8.load(TestSerializableClassA.serializer(), input))
}
@Test
fun testSerializableClassA() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byte: Byte = 66,
@JceId(1) val short: Short = 123,
@JceId(3) val int: Int = 123456,
@JceId(8) val float: Float = 123f,
@JceId(15) val long: Long = 123456789123456789L,
@JceId(16) val double: Double = 123456.0,
@JceId(17) val boolean: Boolean = true,
@JceId(11111) val nullable: Int? = null,
@JceId(111112) val nullable2: Int? = null,
@JceId(111113) val optional: Int = 123
)
val input = buildPacket {
writeJceHead(BYTE, 0)
writeByte(66)
writeJceHead(SHORT, 1)
writeShort(123)
writeJceHead(INT, 3)
writeInt(123456)
writeJceHead(FLOAT, 8)
writeFloat(123f)
writeJceHead(LONG, 15)
writeLong(123456789123456789L)
writeJceHead(DOUBLE, 16)
writeDouble(123456.0)
writeJceHead(BYTE, 17)
writeByte(1) // boolean
}
assertEquals(TestSerializableClassA(), Jce.UTF_8.load(TestSerializableClassA.serializer(), input))
}
@Test
fun testNoSuchField() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byte: Byte = 66,
@JceId(1) val short: Short = 123,
@JceId(3) val int: Int
)
val input = buildPacket {
writeJceHead(BYTE, 0)
writeByte(66)
writeJceHead(SHORT, 1)
writeShort(123)
}
assertFailsWith<MissingFieldException> { Jce.UTF_8.load(TestSerializableClassA.serializer(), input) }
}
@Test
fun testHeadSkip() {
val input = JceInput(buildPacket {
writeJceHead(BYTE, 0)
writeByte(66)
writeJceHead(SHORT, 1)
writeShort(123)
writeJceHead(INT, 3)
writeInt(123456)
writeJceHead(FLOAT, 8)
writeFloat(123f)
writeJceHead(LONG, 15)
writeLong(123456789123456789L)
writeJceHead(DOUBLE, 16)
writeDouble(123456.0)
writeJceHead(BYTE, 17)
writeByte(1) // boolean
}, JceCharset.UTF8)
assertEquals(123456, input.skipToHeadAndUseIfPossibleOrFail(3) { input.readJceIntValue(it) })
assertEquals(true, input.skipToHeadAndUseIfPossibleOrFail(17) { input.readJceBooleanValue(it) })
assertFailsWith<IllegalStateException> {
input.skipToHeadAndUseIfPossibleOrFail(18) {
error("test failed")
}
}
}
@Test
fun testReadPrimitive() {
val input = JceInput(buildPacket {
writeJceHead(BYTE, 0)
writeByte(66)
writeJceHead(SHORT, 1)
writeShort(123)
writeJceHead(INT, 3)
writeInt(123456)
writeJceHead(FLOAT, 8)
writeFloat(123f)
writeJceHead(LONG, 15)
writeLong(123456789123456789L)
writeJceHead(DOUBLE, 16)
writeDouble(123456.0)
writeJceHead(BYTE, 17)
writeByte(1) // boolean
}, JceCharset.UTF8)
assertEquals(66, input.useHead { input.readJceByteValue(it) })
assertEquals(123, input.useHead { input.readJceShortValue(it) })
assertEquals(123456, input.useHead { input.readJceIntValue(it) })
assertEquals(123f, input.useHead { input.readJceFloatValue(it) })
assertEquals(123456789123456789, input.useHead { input.readJceLongValue(it) })
assertEquals(123456.0, input.useHead { input.readJceDoubleValue(it) })
assertEquals(true, input.useHead { input.readJceBooleanValue(it) })
}
}

View File

@ -11,11 +11,11 @@
package test
import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.Input
import io.ktor.utils.io.core.readAvailable
import io.ktor.utils.io.core.use
import io.ktor.utils.io.pool.useInstance
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Input
import kotlinx.io.core.readAvailable
import kotlinx.io.core.use
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.utils.DefaultLogger
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.MiraiLoggerWithSwitch
@ -35,7 +35,7 @@ inline fun ByteArray.debugPrintThis(name: String): ByteArray {
return this
}
@UseExperimental(ExperimentalContracts::class, MiraiInternalAPI::class)
@OptIn(ExperimentalContracts::class, MiraiInternalAPI::class)
inline fun <R> Input.debugIfFail(name: String = "", onFail: (ByteArray) -> ByteReadPacket = { it.toReadPacket() }, block: ByteReadPacket.() -> R): R {
contract {

View File

@ -23,7 +23,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
* QQ for Android
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
actual object QQAndroid : BotFactory {
/**

View File

@ -9,19 +9,189 @@
package net.mamoe.mirai.qqandroid
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.consumeEachBufferRange
import io.ktor.utils.io.core.Input
import io.ktor.utils.io.core.readBytes
import kotlinx.coroutines.io.*
import kotlinx.io.core.*
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.ContextImpl
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.io.ByteArrayPool
import net.mamoe.mirai.utils.io.toReadPacket
import java.nio.ByteBuffer
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
@Suppress("FunctionName")
internal fun QQAndroidBot(account: BotAccount, configuration: BotConfiguration): QQAndroidBot = QQAndroidBot(ContextImpl(), account, configuration)
internal fun QQAndroidBot(account: BotAccount, configuration: BotConfiguration): QQAndroidBot =
QQAndroidBot(ContextImpl(), account, configuration)
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
internal actual class QQAndroidBot actual constructor(
context: Context,
account: BotAccount,
configuration: BotConfiguration
) : QQAndroidBotBase(context, account, configuration)
) : QQAndroidBotBase(context, account, configuration)
@OptIn(MiraiInternalAPI::class)
@Suppress("DEPRECATION")
internal actual fun ByteReadChannel.toKotlinByteReadChannel(): kotlinx.coroutines.io.ByteReadChannel {
return object : kotlinx.coroutines.io.ByteReadChannel {
override val availableForRead: Int
get() = this@toKotlinByteReadChannel.availableForRead
override val isClosedForRead: Boolean
get() = this@toKotlinByteReadChannel.isClosedForRead
override val isClosedForWrite: Boolean
get() = this@toKotlinByteReadChannel.isClosedForWrite
@Suppress("DEPRECATION_ERROR", "OverridingDeprecatedMember")
override var readByteOrder: ByteOrder
get() = when (this@toKotlinByteReadChannel.readByteOrder) {
io.ktor.utils.io.core.ByteOrder.BIG_ENDIAN -> ByteOrder.BIG_ENDIAN
io.ktor.utils.io.core.ByteOrder.LITTLE_ENDIAN -> ByteOrder.LITTLE_ENDIAN
}
set(value) {
this@toKotlinByteReadChannel.readByteOrder = when (value) {
ByteOrder.BIG_ENDIAN -> io.ktor.utils.io.core.ByteOrder.BIG_ENDIAN
ByteOrder.LITTLE_ENDIAN -> io.ktor.utils.io.core.ByteOrder.LITTLE_ENDIAN
}
}
@Suppress("DEPRECATION_ERROR", "DEPRECATION", "OverridingDeprecatedMember")
override val totalBytesRead: Long
get() = this@toKotlinByteReadChannel.totalBytesRead
override fun cancel(cause: Throwable?): Boolean = this@toKotlinByteReadChannel.cancel(cause)
override suspend fun consumeEachBufferRange(visitor: ConsumeEachBufferVisitor) = this@toKotlinByteReadChannel.consumeEachBufferRange(visitor)
override suspend fun discard(max: Long): Long = this@toKotlinByteReadChannel.discard(max)
@Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE")
@ExperimentalIoApi
override fun <R> lookAhead(visitor: LookAheadSession.() -> R): R {
return this@toKotlinByteReadChannel.lookAhead l@{
visitor(object : LookAheadSession{
override fun consumed(n: Int) {
return this@l.consumed(n)
}
override fun request(skip: Int, atLeast: Int): ByteBuffer? {
return this@l.request(skip, atLeast)
}
})
}
}
@Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE")
@ExperimentalIoApi
override suspend fun <R> lookAheadSuspend(visitor: suspend LookAheadSuspendSession.() -> R): R =
this@toKotlinByteReadChannel.lookAheadSuspend l@{
visitor(object : LookAheadSuspendSession {
override suspend fun awaitAtLeast(n: Int): Boolean {
return this@l.awaitAtLeast(n)
}
override fun consumed(n: Int) {
return this@l.consumed(n)
}
override fun request(skip: Int, atLeast: Int): ByteBuffer? {
return this@l.request(skip, atLeast)
}
})
}
override suspend fun read(min: Int, consumer: (ByteBuffer) -> Unit) =
this@toKotlinByteReadChannel.read(min, consumer)
override suspend fun readAvailable(dst: ByteBuffer): Int = this@toKotlinByteReadChannel.readAvailable(dst)
override suspend fun readAvailable(dst: ByteArray, offset: Int, length: Int): Int =
this@toKotlinByteReadChannel.readAvailable(dst, offset, length)
override suspend fun readAvailable(dst: IoBuffer): Int {
ByteArrayPool.useInstance {
val read = this@toKotlinByteReadChannel.readAvailable(it, 0, it.size)
dst.writeFully(it, 0, read)
return read
}
}
override suspend fun readBoolean(): Boolean = this@toKotlinByteReadChannel.readBoolean()
override suspend fun readByte(): Byte = this@toKotlinByteReadChannel.readByte()
override suspend fun readDouble(): Double = this@toKotlinByteReadChannel.readDouble()
override suspend fun readFloat(): Float = this@toKotlinByteReadChannel.readFloat()
override suspend fun readFully(dst: ByteBuffer): Int {
TODO("not implemented")
}
override suspend fun readFully(dst: ByteArray, offset: Int, length: Int) =
this@toKotlinByteReadChannel.readFully(dst, offset, length)
override suspend fun readFully(dst: IoBuffer, n: Int) {
ByteArrayPool.useInstance {
dst.writeFully(it, 0, this.readAvailable(it, 0, it.size))
}
}
override suspend fun readInt(): Int = this@toKotlinByteReadChannel.readInt()
override suspend fun readLong(): Long = this@toKotlinByteReadChannel.readLong()
override suspend fun readPacket(size: Int, headerSizeHint: Int): ByteReadPacket {
return this@toKotlinByteReadChannel.readPacket(size, headerSizeHint).readBytes().toReadPacket()
}
override suspend fun readRemaining(limit: Long, headerSizeHint: Int): ByteReadPacket {
return this@toKotlinByteReadChannel.readRemaining(limit, headerSizeHint).readBytes().toReadPacket()
}
@OptIn(ExperimentalIoApi::class)
@ExperimentalIoApi
override fun readSession(consumer: ReadSession.() -> Unit) {
@Suppress("DEPRECATION")
this@toKotlinByteReadChannel.readSession lambda@{
consumer(object : ReadSession {
override val availableForRead: Int
get() = this@lambda.availableForRead
override fun discard(n: Int): Int = this@lambda.discard(n)
override fun request(atLeast: Int): IoBuffer? {
val ioBuffer: io.ktor.utils.io.core.IoBuffer = this@lambda.request(atLeast) ?: return null
val buffer = IoBuffer.Pool.borrow()
val bytes = (ioBuffer as Input).readBytes()
buffer.writeFully(bytes)
return buffer
}
})
}
}
override suspend fun readShort(): Short = this@toKotlinByteReadChannel.readShort()
@Suppress("EXPERIMENTAL_OVERRIDE", "EXPERIMENTAL_API_USAGE")
@ExperimentalIoApi
override suspend fun readSuspendableSession(consumer: suspend SuspendableReadSession.() -> Unit) =
this@toKotlinByteReadChannel.readSuspendableSession l@{
consumer(object : SuspendableReadSession {
override val availableForRead: Int
get() = this@l.availableForRead
override suspend fun await(atLeast: Int): Boolean = this@l.await(atLeast)
override fun discard(n: Int): Int = this@l.discard(n)
override fun request(atLeast: Int): IoBuffer? {
@Suppress("DuplicatedCode") val ioBuffer: io.ktor.utils.io.core.IoBuffer =
this@l.request(atLeast) ?: return null
val buffer = IoBuffer.Pool.borrow()
val bytes = (ioBuffer as Input).readBytes()
buffer.writeFully(bytes)
return buffer
}
})
}
override suspend fun readUTF8Line(limit: Int): String? = this@toKotlinByteReadChannel.readUTF8Line(limit)
override suspend fun <A : Appendable> readUTF8LineTo(out: A, limit: Int): Boolean =
this@toKotlinByteReadChannel.readUTF8LineTo(out, limit)
}
}

View File

@ -11,7 +11,7 @@ package net.mamoe.mirai.qqandroid.io.serialization
/*
import io.ktor.utils.io.core.readBytes
import kotlinx.io.core.readBytes
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.JceOutput

View File

@ -28,7 +28,7 @@ fun main() {
println(
File(
"""
E:\Projects\QQAndroidFF\app\src\main\java\tencent\im\oidb\cmd0x857
E:\Projects\QQAndroidFF\app\src\main\java\tencent\im\msgrevoke
""".trimIndent()
)
.generateUnarrangedClasses().toMutableList().arrangeClasses().joinToString("\n\n")
@ -161,7 +161,7 @@ data class PBFieldInfo(
}
}
@UseExperimental(ExperimentalUnsignedTypes::class)
@OptIn(ExperimentalUnsignedTypes::class)
fun String.generateProtoBufDataClass(): GeneratedClass {
if (this.indexOf("extends") == -1) {
val javaClassname = substringBetween("class", "{")
@ -367,7 +367,7 @@ fun String.getNumericalValue(): Int? {
return this.filter { it in '0'..'9' }.toDoubleOrNull()?.toInt()
}
@UseExperimental(MiraiDebugAPI::class)
@OptIn(MiraiDebugAPI::class)
fun ProtoType.mapToKotlinType(): String {
return when (this) {
ProtoType.VAR_INT -> "Int"

View File

@ -11,6 +11,7 @@ plugins {
val kotlinVersion: String by rootProject.ext
val atomicFuVersion: String by rootProject.ext
val coroutinesVersion: String by rootProject.ext
val kotlinXIoVersion: String by rootProject.ext
val coroutinesIoVersion: String by rootProject.ext
@ -51,48 +52,38 @@ kotlin {
)
}
jvm("jvm") {
}
jvm()
sourceSets {
all {
languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.useExperimentalAnnotation("kotlin.Experimental")
}
commonMain {
dependencies {
api(kotlin("stdlib", kotlinVersion))
api(kotlin("serialization", kotlinVersion))
api("org.jetbrains.kotlinx:atomicfu:$atomicFuVersion")
api(kotlinx("coroutines-io", coroutinesIoVersion))
api(kotlinx("coroutines-core", coroutinesVersion))
}
}
commonMain {
dependencies {
api(kotlin("reflect", kotlinVersion))
api(kotlin("serialization", kotlinVersion))
api(kotlinx("coroutines-core-common", coroutinesVersion))
api(kotlinx("serialization-runtime-common", serializationVersion))
api(kotlinx("serialization-protobuf-common", serializationVersion))
api(kotlinx("io", kotlinXIoVersion))
api(kotlinx("coroutines-io", coroutinesIoVersion))
api(kotlinx("coroutines-core", coroutinesVersion))
api("org.jetbrains.kotlinx:atomicfu-common:$atomicFuVersion")
api(ktor("http-cio", ktorVersion))
api(ktor("http", ktorVersion))
api(ktor("client-core-jvm", ktorVersion))
api(ktor("client-cio", ktorVersion))
api(ktor("client-core", ktorVersion))
api(ktor("network", ktorVersion))
//implementation("io.ktor:ktor-io:1.3.0-beta-1")
//runtimeOnly(files("build/classes/kotlin/metadata/main")) // classpath is not properly set by IDE
}
}
commonTest {
dependencies {
implementation(kotlin("test-annotations-common"))
implementation(kotlin("test-common"))
//runtimeOnly(files("build/classes/kotlin/metadata/test")) // classpath is not properly set by IDE
}
}
@ -101,8 +92,11 @@ kotlin {
dependencies {
api(kotlin("reflect", kotlinVersion))
api(kotlinx("io-jvm", kotlinXIoVersion))
api(kotlinx("serialization-runtime", serializationVersion))
api(kotlinx("serialization-protobuf", serializationVersion))
api(kotlinx("coroutines-android", coroutinesVersion))
api(kotlinx("coroutines-io-jvm", coroutinesIoVersion))
api(ktor("client-android", ktorVersion))
}
@ -125,10 +119,11 @@ kotlin {
api(kotlin("reflect", kotlinVersion))
api(ktor("client-core-jvm", ktorVersion))
api(kotlinx("io-jvm", kotlinXIoVersion))
api(kotlinx("serialization-runtime", serializationVersion))
api(kotlinx("coroutines-io", coroutinesIoVersion))
api(kotlinx("serialization-protobuf", serializationVersion))
api(kotlinx("coroutines-io-jvm", coroutinesIoVersion))
api(kotlinx("io-jvm", coroutinesIoVersion))
api(kotlinx("coroutines-core", coroutinesVersion))
api("org.bouncycastle:bcprov-jdk15on:1.64")
runtimeOnly(files("build/classes/kotlin/jvm/main")) // classpath is not properly set by IDE

View File

@ -2,8 +2,8 @@
package net.mamoe.mirai
import io.ktor.utils.io.ByteReadChannel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.io.ByteReadChannel
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.AddFriendResult
import net.mamoe.mirai.message.MessageReceipt
@ -24,7 +24,9 @@ import net.mamoe.mirai.utils.*
* @see kotlinx.coroutines.isActive 判断 [Bot] 是否正常运行中. (在线, 且没有被 [close])
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@UseExperimental(MiraiInternalAPI::class, LowLevelAPI::class, MiraiExperimentalAPI::class, JavaHappyAPI::class)
@OptIn(
MiraiInternalAPI::class, LowLevelAPI::class, MiraiExperimentalAPI::class, JavaHappyAPI::class
)
actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIAccessor, BotJavaHappyAPI() {
actual companion object {
/**
@ -54,12 +56,6 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA
*/
actual abstract val context: Context
/**
* 账号信息
*/
@MiraiInternalAPI
actual abstract val account: BotAccount
/**
* QQ 号码. 实际类型为 uint
*/
@ -234,6 +230,6 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA
*/
actual abstract fun close(cause: Throwable?)
@UseExperimental(LowLevelAPI::class, MiraiExperimentalAPI::class)
@OptIn(LowLevelAPI::class, MiraiExperimentalAPI::class)
actual final override fun toString(): String = "Bot(${uin})"
}

View File

@ -132,7 +132,7 @@ actual abstract class BotJavaHappyAPI actual constructor() {
message: String? = null,
remark: String? = null
): AddFriendResult {
@UseExperimental(MiraiExperimentalAPI::class)
@OptIn(MiraiExperimentalAPI::class)
return runBlocking { addFriend(id, message, remark) }
}
@ -170,7 +170,7 @@ actual abstract class BotJavaHappyAPI actual constructor() {
}
// !! 不要 crossinline, 会编译失败
@UseExperimental(ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
internal fun <R, C : CoroutineScope> C.future(block: suspend C.() -> R): Future<R> {
val future = object : Future<R> {
val value: CompletableDeferred<R> = CompletableDeferred()
@ -215,7 +215,7 @@ internal fun <R, C : CoroutineScope> C.future(block: suspend C.() -> R): Future<
}
launch {
@UseExperimental(ExperimentalCoroutinesApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
future.value.completeWith(kotlin.runCatching { block() })
}

View File

@ -33,7 +33,7 @@ import net.mamoe.mirai.utils.WeakRefProperty
* @author Him188moe
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@UseExperimental(MiraiInternalAPI::class, JavaHappyAPI::class)
@OptIn(MiraiInternalAPI::class, JavaHappyAPI::class)
actual abstract class Contact : CoroutineScope, ContactJavaHappyAPI() {
/**
* 这个联系人所属 [Bot].

View File

@ -10,8 +10,8 @@
package net.mamoe.mirai.contact
import android.graphics.Bitmap
import io.ktor.utils.io.core.Input
import kotlinx.coroutines.Dispatchers
import kotlinx.io.core.Input
import net.mamoe.mirai.Bot
import net.mamoe.mirai.JavaHappyAPI
import net.mamoe.mirai.event.events.*

View File

@ -21,7 +21,7 @@ import net.mamoe.mirai.utils.WeakRefProperty
* 群成员.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@UseExperimental(MiraiInternalAPI::class, JavaHappyAPI::class)
@OptIn(MiraiInternalAPI::class, JavaHappyAPI::class)
actual abstract class Member : MemberJavaHappyAPI() {
/**
* 所在的群.

View File

@ -16,7 +16,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 平台相关扩展
*/
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual constructor() : MessagePacketBase<TSender, TSubject>() {
// suspend inline fun uploadImage(image: Bitmap): Image = subject.uploadImage(image)
//suspend inline fun uploadImage(image: URL): Image = subject.uploadImage(image)

View File

@ -28,7 +28,7 @@ import net.mamoe.mirai.utils.unsafeWeakRef
* @see MessageReceipt.sourceTime 源时间
*/
@Suppress("FunctionName")
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
actual open class MessageReceipt<C : Contact> actual constructor(
actual val source: MessageSource,
target: C,
@ -94,7 +94,7 @@ actual open class MessageReceipt<C : Contact> actual constructor(
*/
actual open suspend fun quote(): QuoteReplyToSend {
this.source.ensureSequenceIdAvailable()
@UseExperimental(LowLevelAPI::class)
@OptIn(LowLevelAPI::class)
return _unsafeQuote()
}

View File

@ -12,9 +12,9 @@
package net.mamoe.mirai.message
import android.graphics.Bitmap
import io.ktor.utils.io.core.Input
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.io.core.Input
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.utils.OverFileSizeMaxException
@ -36,28 +36,31 @@ import java.net.URL
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend fun Bitmap.sendTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
suspend fun <C : Contact> Bitmap.sendTo(contact: C): MessageReceipt<C> =
withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
/**
* [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend fun URL.sendAsImageTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
suspend fun <C : Contact> URL.sendAsImageTo(contact: C): MessageReceipt<C> =
withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
/**
* [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend fun Input.sendAsImageTo(contact: Contact) = withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
suspend fun <C : Contact> Input.sendAsImageTo(contact: C): MessageReceipt<C> =
withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
/**
* [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend fun InputStream.sendAsImageTo(contact: Contact) =
suspend fun <C : Contact> InputStream.sendAsImageTo(contact: C): MessageReceipt<C> =
withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
/**
@ -65,9 +68,9 @@ suspend fun InputStream.sendAsImageTo(contact: Contact) =
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend fun File.sendAsImageTo(contact: Contact) {
suspend fun <C : Contact> File.sendAsImageTo(contact: C): MessageReceipt<C> {
require(this.exists() && this.canRead())
withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
return withContext(Dispatchers.IO) { toExternalImage() }.sendTo(contact)
}
// endregion
@ -124,35 +127,36 @@ suspend fun File.uploadAsImage(contact: Contact): Image {
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend inline fun Contact.sendImage(bufferedImage: Bitmap) = bufferedImage.sendTo(this)
suspend inline fun <C : Contact> C.sendImage(bufferedImage: Bitmap): MessageReceipt<C> = bufferedImage.sendTo(this)
/**
* [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend inline fun Contact.sendImage(imageUrl: URL) = imageUrl.sendAsImageTo(this)
suspend inline fun <C : Contact> C.sendImage(imageUrl: URL): MessageReceipt<C> = imageUrl.sendAsImageTo(this)
/**
* [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend inline fun Contact.sendImage(imageInput: Input) = imageInput.sendAsImageTo(this)
suspend inline fun <C : Contact> C.sendImage(imageInput: Input): MessageReceipt<C> = imageInput.sendAsImageTo(this)
/**
* [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend inline fun Contact.sendImage(imageStream: InputStream) = imageStream.sendAsImageTo(this)
suspend inline fun <C : Contact> C.sendImage(imageStream: InputStream): MessageReceipt<C> =
imageStream.sendAsImageTo(this)
/**
* [Dispatchers.IO] 中将文件作为图片发送到指定联系人
* @throws OverFileSizeMaxException
*/
@Throws(OverFileSizeMaxException::class)
suspend inline fun Contact.sendImage(file: File) = file.sendAsImageTo(this)
suspend inline fun <C : Contact> C.sendImage(file: File): MessageReceipt<C> = file.sendAsImageTo(this)
// endregion

View File

@ -13,13 +13,14 @@ package net.mamoe.mirai.utils
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.Input
import io.ktor.utils.io.core.copyTo
import io.ktor.utils.io.errors.IOException
import io.ktor.utils.io.streams.asOutput
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
import kotlinx.io.core.Input
import kotlinx.io.core.IoBuffer
import kotlinx.io.core.copyTo
import kotlinx.io.errors.IOException
import kotlinx.io.streams.asInput
import kotlinx.io.streams.asOutput
import java.io.File
import java.io.InputStream
import java.net.URL
@ -30,10 +31,11 @@ import java.net.URL
/**
* 读取 [BufferedImage] 的属性, 然后构造 [ExternalImage]
* 读取 [Bitmap] 的属性, 然后构造 [ExternalImage]
*/
@Suppress("UNUSED_PARAMETER")
@Throws(IOException::class)
fun Bitmap.toExternalImage(formatName: String = "gif"): Nothing {
fun Bitmap.toExternalImage(formatName: String = "gif"): ExternalImage {
TODO()
}
@ -42,6 +44,7 @@ fun Bitmap.toExternalImage(formatName: String = "gif"): Nothing {
/**
* 读取文件头识别图片属性, 然后构造 [ExternalImage]
*/
@OptIn(MiraiInternalAPI::class)
@Throws(IOException::class)
fun File.toExternalImage(): ExternalImage {
val input = BitmapFactory.decodeFile(this.absolutePath)
@ -50,9 +53,10 @@ fun File.toExternalImage(): ExternalImage {
return ExternalImage(
width = input.width,
height = input.height,
md5 = this.inputStream().use { it.md5() },
md5 = this.inputStream().use { MiraiPlatformUtils.md5(it) },
imageFormat = this.nameWithoutExtension,
input = this.inputStream(),
input = this.inputStream().asInput(IoBuffer.Pool),
inputSize = this.length(),
filename = this.name
)
}
@ -68,8 +72,8 @@ suspend inline fun File.suspendToExternalImage(): ExternalImage = withContext(IO
@Throws(IOException::class)
fun URL.toExternalImage(): ExternalImage {
val file = createTempFile().apply { deleteOnExit() }
file.outputStream().use { output ->
openStream().use { input ->
file.outputStream().asOutput().use { output ->
openStream().asInput().use { input ->
input.copyTo(output)
}
output.flush()
@ -121,6 +125,7 @@ fun Input.toExternalImage(): ExternalImage {
*/
suspend inline fun Input.suspendToExternalImage(): ExternalImage = withContext(IO) { toExternalImage() }
/*
/**
* 保存为临时文件然后调用 [File.toExternalImage].
*/
@ -132,4 +137,4 @@ suspend fun ByteReadChannel.toExternalImage(): ExternalImage {
}
return file.suspendToExternalImage()
}
}*/

View File

@ -7,34 +7,42 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("unused")
package net.mamoe.mirai.utils
import android.annotation.SuppressLint
import android.net.wifi.WifiManager
import android.os.Build
import android.telephony.TelephonyManager
import io.ktor.utils.io.core.toByteArray
import kotlinx.io.core.toByteArray
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import net.mamoe.mirai.utils.MiraiPlatformUtils.localIpAddress
import net.mamoe.mirai.utils.MiraiPlatformUtils.md5
import java.io.File
/**
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
*/
@UseExperimental(UnstableDefault::class)
@OptIn(UnstableDefault::class)
fun File.loadAsDeviceInfo(context: Context): DeviceInfo {
if (!this.exists() || this.length() == 0L) {
return SystemDeviceInfo(context).also {
this.writeText(Json.plain.stringify(SystemDeviceInfo.serializer(), it))
this.writeText(JSON.stringify(SystemDeviceInfo.serializer(), it))
}
}
return Json.nonstrict.parse(DeviceInfoData.serializer(), this.readText()).also {
return JSON.parse(DeviceInfoData.serializer(), this.readText()).also {
it.context = context
}
}
@OptIn(UnstableDefault::class)
private val JSON = Json(JsonConfiguration.Default)
/**
* 部分引用指向 [Build].
* 部分需要权限, 若无权限则会使用默认值.
@ -96,6 +104,7 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
(context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager).connectionInfo.ssid.toByteArray()
}.getOrElse { byteArrayOf() }
@OptIn(MiraiInternalAPI::class)
override val imsiMd5: ByteArray
@SuppressLint("HardwareIds")
get() = md5(kotlin.runCatching {
@ -111,6 +120,8 @@ actual open class SystemDeviceInfo actual constructor() : DeviceInfo() {
(context.applicationContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).deviceId
}
}.getOrElse { "" }
@OptIn(MiraiInternalAPI::class)
override val ipAddress: ByteArray get() = localIpAddress().split(".").map { it.toByte() }.takeIf { it.size == 4 }?.toByteArray() ?: byteArrayOf()
override val androidId: ByteArray get() = Build.ID.toByteArray()
override val apn: ByteArray get() = "wifi".toByteArray()

View File

@ -4,10 +4,9 @@ import android.os.Build
private var isAddSuppressedSupported: Boolean = true
@MiraiInternalAPI
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
actual fun Throwable.addSuppressed(e: Throwable) {
if (this === e) {
@PublishedApi
internal actual fun Throwable.addSuppressedMirai(e: Throwable) {
if (this == e) {
return
}
if (!isAddSuppressedSupported) {

View File

@ -10,7 +10,8 @@
package net.mamoe.mirai.utils.cryptor
import android.annotation.SuppressLint
import net.mamoe.mirai.utils.md5
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.MiraiPlatformUtils.md5
import java.security.*
import java.security.spec.ECGenParameterSpec
import java.security.spec.X509EncodedKeySpec
@ -71,6 +72,7 @@ actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
.genKeyPair())
}
@OptIn(MiraiInternalAPI::class)
actual fun calculateShareKey(
privateKey: ECDHPrivateKey,
publicKey: ECDHPublicKey

View File

@ -9,12 +9,12 @@
package net.mamoe.mirai.utils.io
import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.Closeable
import io.ktor.utils.io.nio.readPacketAtMost
import io.ktor.utils.io.nio.writePacket
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Closeable
import kotlinx.io.nio.readPacketAtMost
import kotlinx.io.nio.writePacket
import java.net.InetSocketAddress
import java.nio.channels.DatagramChannel
import java.nio.channels.ReadableByteChannel

View File

@ -9,13 +9,13 @@
package net.mamoe.mirai.utils.io
import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.Closeable
import io.ktor.utils.io.core.ExperimentalIoApi
import io.ktor.utils.io.streams.readPacketAtMost
import io.ktor.utils.io.streams.writePacket
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Closeable
import kotlinx.io.core.ExperimentalIoApi
import kotlinx.io.streams.readPacketAtMost
import kotlinx.io.streams.writePacket
import net.mamoe.mirai.utils.MiraiInternalAPI
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
@ -80,7 +80,7 @@ actual class PlatformSocket : Closeable {
}
}
@UseExperimental(ExperimentalIoApi::class)
@OptIn(ExperimentalIoApi::class)
actual suspend fun connect(serverHost: String, serverPort: Int) {
withContext(Dispatchers.IO) {
socket = Socket(serverHost, serverPort)

View File

@ -7,96 +7,97 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("NOTHING_TO_INLINE")
package net.mamoe.mirai.utils
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.util.KtorExperimentalAPI
import io.ktor.utils.io.pool.useInstance
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.utils.io.ByteArrayPool
import java.io.ByteArrayOutputStream
import java.io.DataInput
import java.io.EOFException
import java.io.InputStream
import java.net.InetAddress
import java.security.MessageDigest
import java.util.zip.Deflater
import java.util.zip.Inflater
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@UseExperimental(KtorExperimentalAPI::class)
actual val Http: HttpClient
get() = HttpClient(CIO)
/**
* Localhost 解析
*/
actual fun localIpAddress(): String = runCatching {
InetAddress.getLocalHost().hostAddress
}.getOrElse { "192.168.1.123" }
/**
* MD5 算法
*
* @return 16 bytes
*/
actual fun md5(byteArray: ByteArray, offset: Int, length: Int): ByteArray =
MessageDigest.getInstance("MD5").apply { update(byteArray, offset, length) }.digest()
fun InputStream.md5(): ByteArray {
val digest = MessageDigest.getInstance("md5")
digest.reset()
this.readInSequence {
digest.update(it.toByte())
}
return digest.digest()
}
fun DataInput.md5(): ByteArray {
val digest = MessageDigest.getInstance("md5")
digest.reset()
val buffer = byteArrayOf(1)
while (true) {
try {
this.readFully(buffer)
} catch (e: EOFException) {
break
}
digest.update(buffer[0])
}
return digest.digest()
}
private inline fun InputStream.readInSequence(block: (Int) -> Unit) {
var read: Int
while (this.read().also { read = it } != -1) {
block(read)
}
}
@UseExperimental(MiraiInternalAPI::class)
actual fun ByteArray.unzip(offset: Int, length: Int): ByteArray {
this.checkOffsetAndLength(offset, length)
if (length == 0) return ByteArray(0)
val inflater = Inflater()
inflater.reset()
ByteArrayOutputStream().use { output ->
inflater.setInput(this, offset, length)
ByteArrayPool.useInstance {
while (!inflater.finished()) {
output.write(it, 0, inflater.inflate(it))
}
}
inflater.end()
return output.toByteArray()
}
}
/**
* 时间戳
*/
actual val currentTimeMillis: Long get() = System.currentTimeMillis()
actual val currentTimeMillis: Long get() = System.currentTimeMillis()
@MiraiInternalAPI
actual object MiraiPlatformUtils {
actual fun unzip(data: ByteArray, offset: Int, length: Int): ByteArray {
data.checkOffsetAndLength(offset, length)
if (length == 0) return ByteArray(0)
val inflater = Inflater()
inflater.reset()
ByteArrayOutputStream().use { output ->
inflater.setInput(data, offset, length)
ByteArrayPool.useInstance {
while (!inflater.finished()) {
output.write(it, 0, inflater.inflate(it))
}
}
inflater.end()
return output.toByteArray()
}
}
actual fun zip(data: ByteArray, offset: Int, length: Int): ByteArray {
data.checkOffsetAndLength(offset, length)
if (length == 0) return ByteArray(0)
val deflater = Deflater()
deflater.setInput(data, offset, length)
deflater.finish()
ByteArrayPool.useInstance {
return it.take(deflater.deflate(it)).toByteArray().also { deflater.end() }
}
}
actual fun md5(data: ByteArray, offset: Int, length: Int): ByteArray {
data.checkOffsetAndLength(offset, length)
return MessageDigest.getInstance("MD5").apply { update(data, offset, length) }.digest()
}
actual inline fun md5(str: String): ByteArray = md5(str.toByteArray())
/**
* Ktor HttpClient. 不同平台使用不同引擎.
*/
@OptIn(KtorExperimentalAPI::class)
actual val Http: HttpClient
get() = HttpClient(CIO)
/**
* Localhost 解析
*/
actual fun localIpAddress(): String = runCatching {
InetAddress.getLocalHost().hostAddress
}.getOrElse { "192.168.1.123" }
fun md5(stream: InputStream): ByteArray {
val digest = MessageDigest.getInstance("md5")
digest.reset()
stream.readInSequence {
digest.update(it.toByte())
}
return digest.digest()
}
private inline fun InputStream.readInSequence(block: (Int) -> Unit) {
var read: Int
while (this.read().also { read = it } != -1) {
block(read)
}
}
}

View File

@ -11,10 +11,10 @@
package net.mamoe.mirai
import io.ktor.utils.io.ByteReadChannel
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.io.ByteReadChannel
import kotlinx.coroutines.launch
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.AddFriendResult
@ -31,6 +31,12 @@ import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmSynthetic
/**
* 登录, 返回 [this]
*/
suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() }
// 任何人都能看到这个方法
/**
* 机器人对象. 一个机器人实例登录一个 QQ 账号.
* Mirai 为多账号设计, 可同时维护多个机器人.
@ -41,7 +47,7 @@ import kotlin.jvm.JvmSynthetic
* @see kotlinx.coroutines.isActive 判断 [Bot] 是否正常运行中. (在线, 且没有被 [close])
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@UseExperimental(MiraiInternalAPI::class, LowLevelAPI::class)
@OptIn(MiraiInternalAPI::class, LowLevelAPI::class)
expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor {
companion object {
/**
@ -70,12 +76,6 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor {
*/
abstract val context: Context
/**
* 账号信息
*/
@MiraiInternalAPI
abstract val account: BotAccount
/**
* QQ 号码. 实际类型为 uint
*/
@ -95,7 +95,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor {
// region contacts
/**
* [_lowLevelNewQQ.id] [Bot.uin] 相同的 [_lowLevelNewQQ] 实例
* [QQ.id] [Bot.uin] 相同的 [_lowLevelNewQQ] 实例
*/
abstract val selfQQ: QQ
@ -172,6 +172,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor {
* 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.relogin]
*
* @throws LoginFailedException
* @see alsoLogin
*/
@JvmName("loginSuspend")
@JvmSynthetic
@ -241,7 +242,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor {
*/
abstract fun close(cause: Throwable? = null)
@UseExperimental(LowLevelAPI::class, MiraiExperimentalAPI::class)
@OptIn(LowLevelAPI::class, MiraiExperimentalAPI::class)
final override fun toString(): String
}

View File

@ -11,9 +11,10 @@
package net.mamoe.mirai
import io.ktor.utils.io.core.toByteArray
import kotlinx.io.core.toByteArray
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.md5
import net.mamoe.mirai.utils.MiraiPlatformUtils
import kotlin.annotation.AnnotationTarget.*
@MiraiInternalAPI
@ -23,9 +24,11 @@ data class BotAccount(
*/
@RawAccountIdUse
val id: Long,
@MiraiExperimentalAPI
@MiraiInternalAPI
val passwordMd5: ByteArray // md5
) {
constructor(id: Long, passwordPlainText: String) : this(id, md5(passwordPlainText.toByteArray()))
constructor(id: Long, passwordPlainText: String) : this(id, MiraiPlatformUtils.md5(passwordPlainText.toByteArray()))
override fun equals(other: Any?): Boolean {
if (this === other) return true
@ -52,5 +55,5 @@ data class BotAccount(
@MiraiInternalAPI
@Retention(AnnotationRetention.SOURCE)
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR)
@Experimental(level = Experimental.Level.WARNING)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class RawAccountIdUse

View File

@ -1,34 +0,0 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("BotHelperKt")
@file:Suppress("unused", "EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/*
* [Bot] 中的方法的捷径
*/
//Contacts
/**
* 登录, 返回 [this]
*/
suspend inline fun <B: Bot> B.alsoLogin(): B = also { login() }
/**
* 取得机器人的 QQ
*/
@Deprecated(message = "Use this.uin instead", replaceWith = ReplaceWith("this.uin"), level = DeprecationLevel.WARNING)
inline val Bot.qqAccount: Long
get() = this.uin

View File

@ -7,7 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("EXPERIMENTAL_API_USAGE")
@file:Suppress("EXPERIMENTAL_API_USAGE", "DEPRECATION_ERROR")
package net.mamoe.mirai
@ -27,7 +27,7 @@ import kotlin.coroutines.CoroutineContext
/*
* 泛型 N 不需要向外(接口)暴露.
*/
@UseExperimental(MiraiExperimentalAPI::class)
@OptIn(MiraiExperimentalAPI::class)
@MiraiInternalAPI
abstract class BotImpl<N : BotNetworkHandler> constructor(
context: Context,
@ -40,12 +40,13 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
?: CoroutineExceptionHandler { _, e -> logger.error("An exception was thrown under a coroutine of Bot", e) })
override val context: Context by context.unsafeWeakRef()
@Suppress("CanBePrimaryConstructorProperty") // for logger
@OptIn(LowLevelAPI::class)
@Suppress("CanBePrimaryConstructorProperty", "OverridingDeprecatedMember") // for logger
final override val account: BotAccount = account
@UseExperimental(RawAccountIdUse::class)
@OptIn(RawAccountIdUse::class)
override val uin: Long
get() = account.id
get() = this.account.id
final override val logger: MiraiLogger by lazy { configuration.botLoggerSupplier(this) }
init {
@ -156,7 +157,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
}
}
logger.info("Initializing BotNetworkHandler")
// logger.info("Initializing BotNetworkHandler")
if (::_network.isInitialized) {
BotReloginEvent(this, cause).broadcast()
@ -172,7 +173,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
// endregion
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
override fun close(cause: Throwable?) {
if (!this.botJob.isActive) {
// already cancelled

View File

@ -36,7 +36,7 @@ import kotlin.jvm.JvmSynthetic
*
* @author Him188moe
*/ // 不要删除多平台结构 !!! kotlin bug
@UseExperimental(MiraiInternalAPI::class, JavaHappyAPI::class)
@OptIn(MiraiInternalAPI::class, JavaHappyAPI::class)
@Suppress("INAPPLICABLE_JVM_NAME")
expect abstract class Contact() : CoroutineScope, ContactJavaHappyAPI {
/**

View File

@ -19,7 +19,7 @@ import net.mamoe.mirai.utils.*
*
* @see ContactList.asSequence
*/
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
@Suppress("unused")
class ContactList<C : Contact>(@MiraiInternalAPI val delegate: LockFreeLinkedList<C>) {
/**
@ -79,7 +79,7 @@ fun <E : Contact> ContactList<E>.toList(): List<E> = toMutableList()
/**
* Collect all the elements into a [MutableList].
*/
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
fun <E : Contact> ContactList<E>.toMutableList(): MutableList<E> = this.delegate.toMutableList()
/**
@ -90,7 +90,7 @@ fun <E : Contact> ContactList<E>.toSet(): Set<E> = toMutableSet()
/**
* Collect all the elements into a [MutableSet].
*/
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
fun <E : Contact> ContactList<E>.toMutableSet(): MutableSet<E> = this.delegate.toMutableSet()
/**
@ -98,7 +98,7 @@ fun <E : Contact> ContactList<E>.toMutableSet(): MutableSet<E> = this.delegate.t
*
* Note that the sequence is dynamic, that is, elements are yielded atomically only when it is required
*/
@UseExperimental(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class)
fun <E : Contact> ContactList<E>.asSequence(): Sequence<E> {
return this.delegate.asSequence()
}

View File

@ -25,7 +25,7 @@ import kotlin.time.ExperimentalTime
* 群成员.
*/ // 不要删除多平台结构, kotlin bug
@Suppress("INAPPLICABLE_JVM_NAME")
@UseExperimental(MiraiInternalAPI::class, JavaHappyAPI::class)
@OptIn(MiraiInternalAPI::class, JavaHappyAPI::class)
expect abstract class Member() : MemberJavaHappyAPI {
/**
* 所在的群.

Some files were not shown because too many files have changed in this diff Show More