Commit 7f338edc authored by Him188's avatar Him188

Move files, modularize project

parent 43daf0f1
# UpdateLog
## Major version 0
# Major version 0
开发版本. 频繁更新, 不保证高稳定性
### `0.10.0` *2019/12/23*
## `0.10.1` 还未发布
**Bot 构造**
`Bot` 构造时修改 `BotConfiguration` 而不是登录时.
移除 `CoroutineScope.Bot`
移除 `suspend Bot(...)`
添加 `Bot(..., BotConfiguration.() -> Unit)`
**其他**
移动部分文件, 模块化
## `0.10.0` *2019/12/23*
**事件优化**
更快的监听过程
现在监听不再是 `suspend`, 而必须显式指定 `CoroutineScope`. 详见 [`Subscribers.kt`](mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt#L69)
......@@ -13,7 +21,7 @@
**其他**
`Contact` 现在实现接口 `CoroutineScope`
### `0.9.0` *2019/12/20*
## `0.9.0` *2019/12/20*
**协议模块独立**
现在 `mirai-core` 只提供基础的抽象类. 具体的各协议实现为 `mirai-core-PROTOCOL`.
这些模块都继承自 `mirai-core`.
......@@ -35,15 +43,15 @@
**此为 API 不兼容更新**, 请将所有无符号标志 `u` 删除即可. 如 `123456u` 改为 `123456`
另还有其他 API 的包名或签名修改. 请使用 IDE 自动修补 import 即可.
### `0.8.2` *2019/12/15*
## `0.8.2` *2019/12/15*
- 修复 GroupId.toGroupInternalId 错误
- 修复解析群消息时小概率出现的一个错误
### `0.8.1` *2019/12/15*
## `0.8.1` *2019/12/15*
- 修复有时群资料无法获取的情况
- 现在 `At.qq`, `Long.qq` 等函数不再是 `suspend`
### `0.8.0` *2019/12/14*
## `0.8.0` *2019/12/14*
协议
- 现在查询群资料时可处理群号无效的情况
- 现在能正常分辨禁言事件包
......@@ -56,28 +64,28 @@
优化
- 日志中, 发送给服务器的包将会被以名字记录, 而不是 id
### `0.7.5` *2019/12/09*
## `0.7.5` *2019/12/09*
- 修复验证码包发出后无回复 (错误的验证码包)
### `0.7.4` *2019/12/08*
## `0.7.4` *2019/12/08*
- 修复 bug
- 优化 JVM 平台上需要验证码时的提示
### `0.7.3` *2019/12/07*
## `0.7.3` *2019/12/07*
- 删除 klock 依赖, 添加 Time.kt. 待将来 kotlin Duration 稳定后替换为 Duration
### `0.7.2` *2019/12/07*
## `0.7.2` *2019/12/07*
- 使所有协议相关类 `internal`
- 去掉一些 `close` 的不应该有的 `suspend`
- `QQ`, `Member`, `Group` 现在继承接口 `CoroutineScope`
-`LoginResult``inline class` 修改为 `enum class`
- 添加和修改了 `BotAccount``Bot` 的构造器
### `0.7.1` *2019/12/05*
## `0.7.1` *2019/12/05*
- 修复禁言时间范围错误的问题
- 禁言的扩展函数现在会传递实际函数的返回值
### `0.7.0` *2019/12/04*
## `0.7.0` *2019/12/04*
协议
- 重新分析验证码包, 解决一些无法解析的情况. (这可能会产生新的问题, 遇到后请提交 issue)
- 重新分析提交密码包
......@@ -97,11 +105,11 @@
- 2 个 Contact.sendMessage 重载改为内联扩展函数 **(需要添加 import)**
- 其他小优化
### `0.6.1` *2019/12/03*
## `0.6.1` *2019/12/03*
- 新增: 无法解析密码包/验证码包时的调试输出. 以兼容更多的设备情况
- 新增: `MessagePacket``At.qq()` 捷径获取 QQ
### `0.6.0` *2019/12/02*
## `0.6.0` *2019/12/02*
- 新增: 禁言群成员 (`Member.mute(TimeSpan|Duration|MonthsSpan|Int|UInt)`)
- 新增: 解禁群成员 (`Member.unmute()`)
- 修复: ContactList key 无法匹配 (Kotlin 内联类型泛型投影错误)
......@@ -104,7 +104,7 @@ kotlin {
api(kotlin("test-junit", kotlinVersion))
implementation("org.pcap4j:pcap4j-distribution:1.8.2")
//runtimeOnly(files("build/classes/kotlin/jvm/test")) // classpath is not properly set by IDE
runtimeOnly(files("build/classes/kotlin/jvm/test")) // classpath is not properly set by IDE
}
}
}
......
......@@ -11,9 +11,6 @@ import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.ImageId0x03
import net.mamoe.mirai.message.data.ImageId0x06
import net.mamoe.mirai.network.packet.KnownPacketId
import net.mamoe.mirai.network.packet.OutgoingPacket
import net.mamoe.mirai.network.packet.SessionKey
import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.timpc.internal.RawGroupInfo
import net.mamoe.mirai.timpc.network.GroupImpl
......@@ -21,13 +18,15 @@ import net.mamoe.mirai.timpc.network.MemberImpl
import net.mamoe.mirai.timpc.network.QQImpl
import net.mamoe.mirai.timpc.network.TIMPCBotNetworkHandler
import net.mamoe.mirai.timpc.network.handler.TemporaryPacketHandler
import net.mamoe.mirai.timpc.network.packet.KnownPacketId
import net.mamoe.mirai.timpc.network.packet.OutgoingPacket
import net.mamoe.mirai.timpc.network.packet.SessionKey
import net.mamoe.mirai.timpc.network.packet.action.*
import net.mamoe.mirai.timpc.network.packet.event.EventPacketFactory
import net.mamoe.mirai.timpc.network.packet.event.FriendOnlineStatusChangedPacket
import net.mamoe.mirai.timpc.network.packet.login.*
import net.mamoe.mirai.timpc.utils.assertUnreachable
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
import net.mamoe.mirai.utils.io.logStacktrace
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
......
......@@ -20,10 +20,14 @@ import net.mamoe.mirai.timpc.network.packet.action.*
import net.mamoe.mirai.timpc.network.packet.event.MemberJoinEventPacket
import net.mamoe.mirai.timpc.network.packet.event.MemberQuitEvent
import net.mamoe.mirai.timpc.sendPacket
import net.mamoe.mirai.utils.OverFileSizeMaxException
import net.mamoe.mirai.timpc.utils.assertUnreachable
import net.mamoe.mirai.timpc.withTIMPCBot
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.Http
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.io.toUHexString
import net.mamoe.mirai.utils.unsafeWeakRef
import kotlin.coroutines.CoroutineContext
internal sealed class ContactImpl : Contact {
......
......@@ -7,6 +7,7 @@ import kotlinx.io.core.*
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.Bot
import net.mamoe.mirai.data.LoginResult
import net.mamoe.mirai.data.OnlineStatus
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.event.BroadcastControllable
import net.mamoe.mirai.event.Cancellable
......@@ -14,15 +15,17 @@ import net.mamoe.mirai.event.Subscribable
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.BotLoginSucceedEvent
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.timpc.TIMPCBot
import net.mamoe.mirai.timpc.network.handler.DataPacketSocketAdapter
import net.mamoe.mirai.timpc.network.handler.TemporaryPacketHandler
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.timpc.network.packet.login.*
import net.mamoe.mirai.utils.LockFreeLinkedList
import net.mamoe.mirai.utils.LoginFailedException
import net.mamoe.mirai.utils.OnlineStatus
import net.mamoe.mirai.utils.NoLog
import net.mamoe.mirai.utils.cryptor.Decrypter
import net.mamoe.mirai.utils.cryptor.NoDecrypter
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.unsafeWeakRef
import kotlin.coroutines.CoroutineContext
......
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS", "unused", "MemberVisibilityCanBePrivate")
package net.mamoe.mirai.network.packet
package net.mamoe.mirai.timpc.network.packet
import kotlinx.io.core.*
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.encryptAndWrite
import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.writeQQ
import kotlin.contracts.ExperimentalContracts
......@@ -63,17 +65,14 @@ inline fun PacketFactory<*, *>.buildOutgoingPacket0(
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
BytePacketBuilder(headerSizeHint).use {
with(it) {
writeFully(head)
writeFully(ver)
writeUShort(id.value)
writeUShort(sequenceId)
block(this)
writeFully(tail)
}
return OutgoingPacket(name, id, sequenceId, it.build())
}
return OutgoingPacket(name, id, sequenceId, buildPacket(headerSizeHint) {
writeFully(head)
writeFully(ver)
writeUShort(id.value.toUShort())
writeUShort(sequenceId)
block(this)
writeFully(tail)
})
}
......
......@@ -2,7 +2,7 @@ package net.mamoe.mirai.timpc.network.packet
import kotlinx.io.core.BytePacketBuilder
import kotlinx.serialization.SerializationStrategy
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.contracts.ExperimentalContracts
......
package net.mamoe.mirai.network.packet
package net.mamoe.mirai.timpc.network.packet
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readBytes
......
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.network.packet
package net.mamoe.mirai.timpc.network.packet
import kotlinx.atomicfu.AtomicInt
import kotlinx.atomicfu.atomic
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
......@@ -9,14 +10,16 @@ import kotlinx.io.core.readBytes
import kotlinx.io.pool.useInstance
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.utils.cryptor.Decrypter
import net.mamoe.mirai.utils.cryptor.DecrypterType
import net.mamoe.mirai.utils.cryptor.readProtoMap
import net.mamoe.mirai.utils.io.ByteArrayPool
import net.mamoe.mirai.utils.io.debugPrint
import net.mamoe.mirai.utils.io.read
import net.mamoe.mirai.utils.io.toUHexString
import net.mamoe.mirai.utils.readProtoMap
/**
* 一种数据包的处理工厂. 它可以解密解码服务器发来的这个包, 也可以编码加密要发送给服务器的这个包
......@@ -40,7 +43,6 @@ abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypter>(val d
*/
abstract suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler): TPacket
@Suppress("DEPRECATION")
fun <T> ByteReadPacket.decodeProtoPacket(
deserializer: DeserializationStrategy<T>,
debuggingTag: String? = null
......@@ -63,10 +65,16 @@ abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypter>(val d
}
companion object {
private val sequenceIdInternal = atomic(1)
private val sequenceId: AtomicInt = atomic(1)
@MiraiInternalAPI
fun atomicNextSequenceId(): UShort = sequenceIdInternal.getAndIncrement().toUShort()
fun atomicNextSequenceId(): UShort {
val id = sequenceId.getAndAdd(1)
if (id > Short.MAX_VALUE.toInt() * 2) {
sequenceId.value = 0
return atomicNextSequenceId()
}
return id.toUShort()
}
}
}
......
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.network.packet
package net.mamoe.mirai.timpc.network.packet
import net.mamoe.mirai.utils.io.toUHexString
/**
* 包 ID.
*/
interface PacketId {
val value: UShort
val factory: PacketFactory<*, *>
}
/**
* 通过 [value] 匹配一个 [IgnoredPacketId] 或 [KnownPacketId], 无匹配则返回一个 [UnknownPacketId].
*/
......@@ -13,13 +22,6 @@ fun matchPacketId(value: UShort): PacketId =
?: KnownPacketId.entries.firstOrNull { it.value.value == value }?.value
?: UnknownPacketId(value)
/**
* 包 ID.
*/
interface PacketId {
val value: UShort
val factory: PacketFactory<*, *>
}
/**
* 用于代表 `null`. 调用任何属性时都将会得到一个 [error]
......@@ -49,7 +51,8 @@ inline class IgnoredPacketId constructor(override val value: UShort) : PacketId
override fun toString(): String = "IgnoredPacketId(${value.toUHexString()})"
}
class KnownPacketId(override val value: UShort, override val factory: PacketFactory<*, *>) : PacketId {
class KnownPacketId(override val value: UShort, override val factory: PacketFactory<*, *>) :
PacketId {
companion object : MutableMap<UShort, KnownPacketId> by mutableMapOf() {
operator fun set(key: UShort, factory: PacketFactory<*, *>) {
this[key] = KnownPacketId(key, factory)
......@@ -65,7 +68,8 @@ class KnownPacketId(override val value: UShort, override val factory: PacketFact
return null
}
inline fun <reified PF : PacketFactory<*, *>> get(): KnownPacketId = getOrNull<PF>() ?: throw NoSuchElementException()
inline fun <reified PF : PacketFactory<*, *>> get(): KnownPacketId = getOrNull<PF>()
?: throw NoSuchElementException()
}
override fun toString(): String = (factory::class.simpleName ?: factory::class.simpleName) + "(${value.toUHexString()})"
......
package net.mamoe.mirai.timpc.network.packet
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
import net.mamoe.mirai.utils.cryptor.DecrypterType
/**
* 会话密匙
*/
inline class SessionKey(override val value: ByteArray) : DecrypterByteArray {
companion object Type : DecrypterType<SessionKey>
}
......@@ -8,9 +8,10 @@ import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.EventPacket
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.data.PreviousNameList
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.io.*
......
......@@ -10,10 +10,10 @@ import net.mamoe.mirai.message.data.ImageId
import net.mamoe.mirai.message.data.ImageId0x06
import net.mamoe.mirai.message.data.requireLength
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.*
......
......@@ -5,8 +5,9 @@ package net.mamoe.mirai.timpc.network.packet.action
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.network.packet.SessionPacketFactory
import net.mamoe.mirai.timpc.network.packet.PacketId
import net.mamoe.mirai.timpc.network.packet.SessionPacketFactory
// 0001
......
......@@ -7,9 +7,11 @@ import kotlinx.io.core.writeFully
import kotlinx.io.core.writeUByte
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.utils.NoLog
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.cryptor.encryptAndWrite
import net.mamoe.mirai.utils.io.writeQQ
/**
......
......@@ -11,8 +11,9 @@ import net.mamoe.mirai.message.data.requireLength
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.EventPacket
import net.mamoe.mirai.data.ImageLink
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.packet.buildSessionProtoPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.timpc.utils.assertUnreachable
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.io.toUHexString
......
......@@ -10,12 +10,13 @@ import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.internal.toPacket
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.internal.RawGroupInfo
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.timpc.utils.unsupportedFlag
import net.mamoe.mirai.timpc.utils.unsupportedType
import net.mamoe.mirai.utils.NoLog
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.*
import kotlin.collections.set
......
......@@ -8,8 +8,9 @@ import net.mamoe.mirai.data.Gender
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.*
inline class AvatarLink(val value: String) : Packet
......
......@@ -6,8 +6,9 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.FriendNameRemark
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.readUShortLVString
import net.mamoe.mirai.utils.io.writeQQ
import net.mamoe.mirai.utils.io.writeZero
......
......@@ -3,11 +3,11 @@
package net.mamoe.mirai.timpc.network.packet.action
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.writeZero
class FriendList : Packet
......
......@@ -7,9 +7,11 @@ import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.internal.toPacket
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.utils.NoLog
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.md5
......
......@@ -6,7 +6,7 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import net.mamoe.mirai.Bot
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.PacketVersion
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.readBoolean
......
......@@ -6,10 +6,10 @@ import kotlinx.io.core.*
import net.mamoe.mirai.Bot
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.utils.NoLog
import net.mamoe.mirai.timpc.network.TIMPCBotNetworkHandler
import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.io.readIoBuffer
/**
......
......@@ -6,7 +6,7 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.ReceiveFriendAddRequestEvent
import net.mamoe.mirai.network.packet.PacketVersion
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.readQQ
import net.mamoe.mirai.utils.io.readUShortLVString
......
......@@ -6,7 +6,7 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import net.mamoe.mirai.Bot
import net.mamoe.mirai.data.EventPacket
import net.mamoe.mirai.network.packet.PacketVersion
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.readQQ
......
......@@ -5,11 +5,12 @@ package net.mamoe.mirai.timpc.network.packet.event
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import kotlinx.io.core.readUByte
import net.mamoe.mirai.data.OnlineStatus
import net.mamoe.mirai.event.events.FriendStatusChanged
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.network.packet.SessionPacketFactory
import net.mamoe.mirai.utils.OnlineStatus
import net.mamoe.mirai.timpc.network.packet.PacketId
import net.mamoe.mirai.timpc.network.packet.SessionPacketFactory
import net.mamoe.mirai.utils.io.readQQ
/**
......@@ -21,7 +22,8 @@ internal object FriendOnlineStatusChangedPacket : SessionPacketFactory<FriendSta
val qq = readQQ()
discardExact(8)
val statusId = readUByte()
val status = OnlineStatus(statusId)
val status = OnlineStatus.ofId(statusId.toInt())
return FriendStatusChanged(handler.bot.getQQ(qq), status)
}
......
......@@ -5,7 +5,7 @@ package net.mamoe.mirai.timpc.network.packet.event
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.Bot
import net.mamoe.mirai.data.EventPacket
import net.mamoe.mirai.network.packet.PacketVersion
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.debugPrint
......
......@@ -8,7 +8,7 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.data.EventPacket
import net.mamoe.mirai.network.packet.PacketVersion
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.io.readQQ
......
......@@ -7,7 +7,7 @@ import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.message.GroupMessage
import net.mamoe.mirai.message.internal.readMessageChain
import net.mamoe.mirai.message.FriendMessage
import net.mamoe.mirai.network.packet.PacketVersion
import net.mamoe.mirai.utils.PacketVersion
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.io.*
......
......@@ -5,9 +5,13 @@ package net.mamoe.mirai.timpc.network.packet.login
import kotlinx.io.core.*
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.OutgoingPacket
import net.mamoe.mirai.timpc.network.packet.PacketFactory
import net.mamoe.mirai.timpc.network.packet.PacketId
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
import net.mamoe.mirai.utils.cryptor.DecrypterType
import net.mamoe.mirai.utils.io.*
internal object CaptchaKey : DecrypterByteArray,
......
......@@ -5,21 +5,20 @@ package net.mamoe.mirai.timpc.network.packet.login
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.writeFully
import kotlinx.io.core.writeUByte
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.OnlineStatus
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
import net.mamoe.mirai.utils.OnlineStatus
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.cryptor.NoDecrypter
import net.mamoe.mirai.utils.cryptor.encryptAndWrite
import net.mamoe.mirai.utils.io.writeHex
import net.mamoe.mirai.utils.io.writeQQ
/**
* 改变在线状态: "我在线上", "隐身" 等
*/
internal object ChangeOnlineStatusPacket : PacketFactory<ChangeOnlineStatusPacket.ChangeOnlineStatusResponse, NoDecrypter>(
NoDecrypter
) {
internal object ChangeOnlineStatusPacket : PacketFactory<ChangeOnlineStatusPacket.ChangeOnlineStatusResponse, NoDecrypter>(NoDecrypter) {
operator fun invoke(
bot: Long,
sessionKey: SessionKey,
......@@ -29,7 +28,7 @@ internal object ChangeOnlineStatusPacket : PacketFactory<ChangeOnlineStatusPacke
writeFully(TIMProtocol.fixVer2)
encryptAndWrite(sessionKey) {
writeHex("01 00")
writeUByte(loginStatus.id)
writeUByte(loginStatus.id.toUByte())
writeHex("00 01 00 01 00 04 00 00 00 00")
}
}
......
......@@ -7,9 +7,11 @@ import kotlinx.io.core.writeFully
import net.mamoe.mirai.event.Subscribable
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.utils.NoLog
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.cryptor.encryptAndWrite
import net.mamoe.mirai.utils.io.writeHex
import net.mamoe.mirai.utils.io.writeQQ
......
......@@ -7,10 +7,13 @@ import net.mamoe.mirai.data.Gender
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.LoginResult
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.OutgoingPacket
import net.mamoe.mirai.timpc.network.packet.PacketFactory
import net.mamoe.mirai.timpc.network.packet.PacketId
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.cryptor.*
import net.mamoe.mirai.utils.io.*
internal object ShareKey : DecrypterByteArray,
......@@ -366,4 +369,9 @@ private fun BytePacketBuilder.writePart2() {
this.writeCRC32()
}
internal fun BytePacketBuilder.writeCRC32() = writeCRC32(getRandomByteArray(16))
internal fun BytePacketBuilder.writeCRC32(key: ByteArray) {
writeFully(key)//key
writeInt(crc32(key))
}
......@@ -7,9 +7,9 @@ import kotlinx.io.core.discardExact
import kotlinx.io.core.writeFully
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.utils.cryptor.encryptAndWrite
import net.mamoe.mirai.utils.io.*
internal inline class SKey(
......
......@@ -5,10 +5,10 @@ package net.mamoe.mirai.timpc.network.packet.login
import kotlinx.io.core.*
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.packet.PacketFactory
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.network.packet.SessionKey
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.PacketFactory
import net.mamoe.mirai.timpc.network.packet.PacketId
import net.mamoe.mirai.timpc.network.packet.SessionKey
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.localIpAddress
......
......@@ -8,9 +8,13 @@ import kotlinx.io.core.readBytes
import kotlinx.io.core.writeFully
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.OutgoingPacket
import net.mamoe.mirai.timpc.network.packet.PacketFactory
import net.mamoe.mirai.timpc.network.packet.PacketId
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
import net.mamoe.mirai.utils.cryptor.DecrypterType
import net.mamoe.mirai.utils.io.*
internal object TouchKey : DecrypterByteArray,
......
package net.mamoe.mirai.timpc.utils
import kotlinx.io.core.toByteArray
private const val GTK_BASE_VALUE: Int = 5381
fun getGTK(sKey: String): Int {
var value = GTK_BASE_VALUE
for (c in sKey.toByteArray()) {
value += (value shl 5) + c.toInt()
}
value = value and Int.MAX_VALUE
return value
}
package net.mamoe.mirai.timpc.utils
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.writeFully
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.protobuf.ProtoBuf
fun <T> BytePacketBuilder.writeProto(serializer: SerializationStrategy<T>, obj: T) = writeFully(ProtoBuf.dump(serializer, obj))
......@@ -16,14 +16,17 @@ import kotlinx.serialization.internal.ArrayListSerializer
import kotlinx.serialization.json.Json
import net.mamoe.mirai.Bot
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.timpc.TIMPC
import net.mamoe.mirai.timpc.network.TIMProtocol
import net.mamoe.mirai.timpc.network.packet.*
import net.mamoe.mirai.timpc.network.packet.event.FriendOnlineStatusChangedPacket
import net.mamoe.mirai.timpc.network.packet.event.IgnoredEventPacket
import net.mamoe.mirai.timpc.network.packet.login.*
import net.mamoe.mirai.utils.DecryptionFailedException
import net.mamoe.mirai.utils.decryptBy
import net.mamoe.mirai.utils.cryptor.Decrypter
import net.mamoe.mirai.utils.cryptor.DecryptionFailedException
import net.mamoe.mirai.utils.cryptor.NoDecrypter
import net.mamoe.mirai.utils.cryptor.decryptBy
import net.mamoe.mirai.utils.io.*
import org.pcap4j.core.BpfProgram.BpfCompileMode
import org.pcap4j.core.PacketListener
......@@ -181,13 +184,13 @@ internal object PacketDebugger {
* 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey`
*/
val sessionKey: SessionKey =
SessionKey("95 F3 24 8E 7B B6 62 AA 98 C0 EE 45 CE CE 2B 69".hexToBytes())
SessionKey("D8 D0 B0 DE 37 53 9B 05 A5 E7 AB 96 B2 AC AD EC".hexToBytes())
// TODO: 2019/12/7 无法访问 internal 是 kotlin bug, KT-34849
/**
* null 则不筛选
*/
val qq: Long? = 761025446
val qq: Long? = null
/**
* 打开后则记录每一个包到文件.
*/
......@@ -204,7 +207,7 @@ internal object PacketDebugger {
//println("raw = " + data.toUHexString())
data.read {
discardExact(3)
val id = net.mamoe.mirai.network.packet.matchPacketId(readUShort())
val id = matchPacketId(readUShort())
val sequenceId = readUShort()
val packetQQ = readQQ()
if (id == KnownPacketId.get<HeartbeatPacket>() || (qq != null && packetQQ != qq))
......@@ -301,7 +304,7 @@ internal object PacketDebugger {
// 3E 03 3F A2 02 00 00 00 01 2E 01 00 00 69 35
discardExact(3)//head
val id = net.mamoe.mirai.network.packet.matchPacketId(readUShort())
val id = net.mamoe.mirai.timpc.network.packet.matchPacketId(readUShort())
val sequence = readUShort().toUHexString()
if (IgnoredPacketIdList.contains(id)) {
return
......
......@@ -3,8 +3,9 @@ package packetdebugger
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import kotlinx.io.core.readUShort
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.network.packet.matchPacketId
import net.mamoe.mirai.timpc.network.packet.PacketId
import net.mamoe.mirai.timpc.network.packet.matchPacketId
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
......
......@@ -3,7 +3,7 @@
package net.mamoe.mirai
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.network.packet.NullPacketId.factory
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.MiraiLogger
import kotlin.coroutines.CoroutineContext
......
......@@ -4,7 +4,7 @@ package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.data.GroupInfo
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
import net.mamoe.mirai.utils.coerceAtLeastOrFail
/**
......
package net.mamoe.mirai.data
/**
* 在线状态
*/
enum class OnlineStatus(val id: Int) {
/**
* 我在线上
*/
ONLINE(11), // 0x0A
/**
* 离线
*/
OFFLINE(21), // 0x02
/**
* 离开
*/
AWAY(31),
/**
* 隐身
*/
INVISIABLE(41),
/**
* 忙碌
*/
BUSY(50), // 0x32
/**
* Q 我吧
*/
Q_ME(60),
/**
* 请勿打扰
*/
DND(70),
/**
* 离线但接收消息
*/
RECEIVE_OFFLINE_MESSAGE(95);
companion object {
fun ofId(id: Int): OnlineStatus = values().first { it.id == id }
fun ofIdOrNull(id: Int): OnlineStatus? = values().firstOrNull { it.id == id }
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ package net.mamoe.mirai.event.events
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.data.EventPacket
import net.mamoe.mirai.utils.OnlineStatus
import net.mamoe.mirai.data.OnlineStatus
data class FriendStatusChanged(
val qq: QQ,
......
......@@ -10,7 +10,7 @@ import net.mamoe.mirai.data.ImageLink
import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
import net.mamoe.mirai.utils.coerceAtLeastOrFail
import kotlin.jvm.JvmName
/**
......
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused")
package net.mamoe.mirai.network.packet
/**
* 包的最后一次修改时间, 和分析时使用的 TIM 版本
*/
@MustBeDocumented
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
annotation class PacketVersion(val date: String, val timVersion: String)
/**
* 带有这个注解的 [Packet] 将不会被记录在 log 中.
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class NoLog
\ No newline at end of file
......@@ -36,3 +36,18 @@ annotation class MiraiExperimentalAPI(
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
annotation class SinceMirai(val version: String)
/**
* 包的最后一次修改时间, 和分析时使用的 TIM 版本
*/
@MustBeDocumented
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
annotation class PacketVersion(val date: String, val timVersion: String)
/**
* 带有这个注解的 [Packet] 将不会被记录在 log 中.
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class NoLog
\ No newline at end of file
......@@ -5,24 +5,4 @@ import kotlinx.io.core.toByteArray
import kotlinx.io.core.writeFully
import net.mamoe.mirai.utils.io.getRandomByteArray
private const val GTK_BASE_VALUE: Int = 5381
fun getGTK(sKey: String): Int {
var value = GTK_BASE_VALUE
for (c in sKey.toByteArray()) {
value += (value shl 5) + c.toInt()
}
value = value and Int.MAX_VALUE
return value
}
@Tested
fun BytePacketBuilder.writeCRC32() = writeCRC32(getRandomByteArray(16))
fun BytePacketBuilder.writeCRC32(key: ByteArray) {
writeFully(key)//key
writeInt(crc32(key))
}
fun md5(str: String): ByteArray = md5(str.toByteArray())
\ No newline at end of file
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE", "unused")
package net.mamoe.mirai.utils
import kotlin.jvm.JvmStatic
/**
* QQ 在线状态
*
* @author Him188moe
* @see net.mamoe.mirai.timpc.network.packet.login.ChangeOnlineStatusPacket
*/
inline class OnlineStatus(
inline val id: UByte
) {
companion object {
/**
* 我在线上
*/
@JvmStatic
val ONLINE = OnlineStatus(0x0Au)
/**
* 忙碌
*/
@JvmStatic
val BUSY = OnlineStatus(0x32u)
/**
* 离线 ? 也可能是被删好友 TODO confirm that
*/
@JvmStatic
val OFFLINE = OnlineStatus(0x02u)
@JvmStatic
val UNKNOWN1 = OnlineStatus(0x20u)
@JvmStatic
val UNKNOWN2 = OnlineStatus(0x46u)
@JvmStatic
val UNKNOWN3 = OnlineStatus(0x14u)
@JvmStatic
val UNKNOWN4 = OnlineStatus(0xC9u)
@JvmStatic
val UNKNOWN5 = OnlineStatus(0x1Eu)
}
// TODO: 2019/10/29 what is 0x20u
// TODO: 2019/11/11 what is 0x46u
// TODO: 2019/11/11 what is 0x14u
// TODO: 2019/11/11 0xC9u
// TODO: 2019/11/11 0x1Eu
}
package net.mamoe.mirai.network.packet
package net.mamoe.mirai.utils.cryptor
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.IoBuffer
import net.mamoe.mirai.utils.decryptBy
import net.mamoe.mirai.utils.io.encryptAndWrite
/**
* 会话密匙
*/
inline class SessionKey(override val value: ByteArray) : DecrypterByteArray {
companion object Type : DecrypterType<SessionKey>
}
/**
* [ByteArray] 解密器
*/
......
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused")
package net.mamoe.mirai.utils
package net.mamoe.mirai.utils.cryptor
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readBytes
......@@ -24,7 +24,11 @@ import kotlin.jvm.JvmStatic
*
* https://www.jianshu.com/p/f888907adaeb
*/
fun ProtoFieldId(serializedId: UInt): ProtoFieldId = ProtoFieldId(protoFieldNumber(serializedId), protoType(serializedId))
fun ProtoFieldId(serializedId: UInt): ProtoFieldId =
ProtoFieldId(
protoFieldNumber(serializedId),
protoType(serializedId)
)
data class ProtoFieldId(
val fieldNumber: Int,
......@@ -78,7 +82,8 @@ enum class ProtoType(val value: Byte, private val typeName: String) {
*
* serializedId = (fieldNumber << 3) | wireType
*/
fun protoType(number: UInt): ProtoType = ProtoType.valueOf(number.toInt().shl(29).ushr(29).toByte())
fun protoType(number: UInt): ProtoType =
ProtoType.valueOf(number.toInt().shl(29).ushr(29).toByte())
/**
* ProtoBuf 序列化后的 id 转为序列前标记的 id
......
package net.mamoe.mirai.utils
package net.mamoe.mirai.utils.cryptor
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.IoBuffer
......@@ -29,7 +29,8 @@ class DecryptionFailedException : Exception {
* @param key 长度至少为 16
* @throws DecryptionFailedException 解密错误时
*/
fun ByteArray.encryptBy(key: ByteArray, length: Int = this.size): ByteArray = TEA.encrypt(this, key, sourceLength = length)
fun ByteArray.encryptBy(key: ByteArray, length: Int = this.size): ByteArray =
TEA.encrypt(this, key, sourceLength = length)
/**
* 在 [ByteArrayPool] 缓存 [this], 然后使用 [key] 加密.
......@@ -339,11 +340,13 @@ private object TEA {
@PublishedApi
@JvmStatic
internal fun encrypt(source: ByteArray, key: ByteArray, sourceLength: Int = source.size): ByteArray = doOption(source, key, sourceLength, true)
internal fun encrypt(source: ByteArray, key: ByteArray, sourceLength: Int = source.size): ByteArray =
doOption(source, key, sourceLength, true)
@PublishedApi
@JvmStatic
internal fun decrypt(source: ByteArray, key: ByteArray, sourceLength: Int = source.size): ByteArray = doOption(source, key, sourceLength, false)
internal fun decrypt(source: ByteArray, key: ByteArray, sourceLength: Int = source.size): ByteArray =
doOption(source, key, sourceLength, false)
private fun ByteArray.pack(offset: Int, len: Int): Long {
var result: Long = 0
......
@file:JvmName("IterableUtil")
package net.mamoe.mirai.utils.internal
import kotlin.jvm.JvmName
internal inline fun <T> MutableIterable<T>.inlinedRemoveIf(predicate: (T) -> Boolean) = iterator().inlinedRemoveIf(predicate)
internal inline fun <T> MutableIterator<T>.inlinedRemoveIf(predicate: (T) -> Boolean) {
while (this.hasNext()) {
if (predicate(this.next())) {
this.remove()
}
}
}
\ No newline at end of file
......@@ -4,15 +4,13 @@ package net.mamoe.mirai.utils.io
import kotlinx.io.core.*
import kotlinx.io.pool.useInstance
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.contact.GroupId
import net.mamoe.mirai.contact.GroupInternalId
import net.mamoe.mirai.utils.Tested
import net.mamoe.mirai.utils.coerceAtMostOrFail
import net.mamoe.mirai.utils.cryptor.encryptBy
import net.mamoe.mirai.utils.currentTime
import net.mamoe.mirai.utils.deviceName
import net.mamoe.mirai.utils.encryptBy
import net.mamoe.mirai.utils.internal.coerceAtMostOrFail
import kotlin.random.Random
import kotlin.random.nextInt
......@@ -28,6 +26,18 @@ fun BytePacketBuilder.writeQQ(qq: Long) = this.writeUInt(qq.toUInt()) // same bi
fun BytePacketBuilder.writeGroup(groupId: GroupId) = this.writeUInt(groupId.value.toUInt())
fun BytePacketBuilder.writeGroup(groupInternalId: GroupInternalId) = this.writeUInt(groupInternalId.value.toUInt())
fun BytePacketBuilder.writeShortLVByteArrayLimitedLength(array: ByteArray, maxLength: Int) {
if (array.size <= maxLength) {
writeShort(array.size.toShort())
writeFully(array)
} else {
writeShort(maxLength.toShort())
repeat(maxLength) {
writeByte(array[it])
}
}
}
fun BytePacketBuilder.writeShortLVByteArray(byteArray: ByteArray) {
this.writeShort(byteArray.size.toShort())
this.writeFully(byteArray)
......@@ -63,8 +73,6 @@ fun BytePacketBuilder.writeHex(uHex: String) {
}
}
fun <T> BytePacketBuilder.writeProto(serializer: SerializationStrategy<T>, obj: T) = writeFully(ProtoBuf.dump(serializer, obj))
fun BytePacketBuilder.writeTLV(tag: UByte, values: UByteArray) {
writeUByte(tag)
......
......@@ -92,6 +92,12 @@ fun String.hexToBytes(): ByteArray =
.map { s -> s.toUByte(16).toByte() }
.toByteArray()
/**
* 每 2 char 为一组, 转换 Hex 为 [ByteArray]
*/
fun String.chunkedHexToBytes(): ByteArray =
this.chunked(2).map { it.toUByte(16).toByte() }.toByteArray()
/**
* 将无符号 Hex 转为 [UByteArray], 有根据 hex 的 [hashCode] 建立的缓存.
*/
......
package mirai.test.testCaptchaPacket
import net.mamoe.mirai.utils.decryptBy
import net.mamoe.mirai.utils.cryptor.decryptBy
import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.toUHexString
......
......@@ -41,7 +41,7 @@ fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
dependencies {
implementation(files("../mirai-core-timpc/build/classes/kotlin/jvm/main")) // IDE bug
runtimeOnly(files("../mirai-core-timpc/build/classes/kotlin/jvm/main")) // IDE bug
implementation(project(":mirai-core-timpc"))
// runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // classpath is not added correctly by IDE
......
......@@ -7,10 +7,10 @@ import kotlinx.serialization.protobuf.ProtoBuf
import kotlinx.serialization.protobuf.ProtoNumberType
import kotlinx.serialization.protobuf.ProtoType
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.readProtoMap
import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.read
import net.mamoe.mirai.utils.io.toUHexString
import net.mamoe.mirai.utils.readProtoMap
import kotlin.reflect.KClass
@Serializable
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment