Adjust class names

This commit is contained in:
Him188 2019-10-24 22:55:33 +08:00
parent 6c6f0a48c7
commit d5bf51a357
32 changed files with 179 additions and 204 deletions

View File

@ -85,7 +85,6 @@ kotlin {
jvmTest {
apply plugin: 'java'
}
all {

View File

@ -46,6 +46,8 @@ sealed class Contact(val bot: Bot, val id: UInt) {
*/
inline class GroupId(val value: UInt)
fun UInt.groupId(): GroupId = GroupId(this)
/**
* 一些群 API 使用的 ID. 在使用时会特别注明
*
@ -62,7 +64,7 @@ inline class GroupInternalId(val value: UInt)
* @author Him188moe
*/
class Group internal constructor(bot: Bot, id: UInt) : Contact(bot, id) {
val internalId = groupNumberToId(id)
val internalId = GroupId(id).toInternalId()
val members: ContactList<QQ>
//todo members
get() = throw UnsupportedOperationException("Not yet supported")
@ -95,43 +97,4 @@ class QQ internal constructor(bot: Bot, number: UInt) : Contact(bot, number) {
override suspend fun sendXMLMessage(message: String) {
TODO()
}
}
fun Group.Companion.groupNumberToId(number: UInt): UInt {//求你别出错
val left: Long = number.toString().let {
if (it.length < 6) {
return@groupNumberToId number
}
it.substring(0, it.length - 6).toLong()
}
val right: Long = number.toString().let {
it.substring(it.length - 6).toLong()
}
return when (left) {
in 1..10 -> {
((left + 202).toString() + right.toString()).toUInt()
}
in 11..19 -> {
((left + 469).toString() + right.toString()).toUInt()
}
in 20..66 -> {
((left + 208).toString() + right.toString()).toUInt()
}
in 67..156 -> {
((left + 1943).toString() + right.toString()).toUInt()
}
in 157..209 -> {
((left + 199).toString() + right.toString()).toUInt()
}
in 210..309 -> {
((left + 389).toString() + right.toString()).toUInt()
}
in 310..499 -> {
((left + 349).toString() + right.toString()).toUInt()
}
else -> number
}
}
}

View File

@ -7,7 +7,7 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.EventScope
import net.mamoe.mirai.event.ListeningStatus
import net.mamoe.mirai.utils.inlinedRemoveIf
import net.mamoe.mirai.utils.internal.inlinedRemoveIf
import kotlin.reflect.KClass
/**

View File

@ -6,9 +6,6 @@ import kotlinx.io.core.*
import net.mamoe.mirai.message.*
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.toUHexString
import net.mamoe.mirai.utils.writeHex
import net.mamoe.mirai.utils.writeShortLVPacket
import net.mamoe.mirai.utils.writeShortLVString
internal fun IoBuffer.parseMessageFace(): Face {
//00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0
@ -38,7 +35,8 @@ internal fun IoBuffer.parseMessageImage0x06(): Image {
discardExact(1)
//MiraiLogger.logDebug(this.toUHexString())
val filenameLength = readShort()
val suffix = readString(filenameLength).substringAfter(".")
discardExact(filenameLength.toInt())
discardExact(8)//03 00 04 00 00 02 9C 04
val length = readShort()//=27
return Image(ImageId(readString(length)))

View File

@ -24,6 +24,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.login.*
import net.mamoe.mirai.network.session
import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.internal.inlinedRemoveIf
import net.mamoe.mirai.utils.io.parseServerPacket
import net.mamoe.mirai.utils.io.toUHexString
import kotlin.coroutines.CoroutineContext
@ -55,23 +56,23 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
temporaryPacketHandler.send(this[ActionPacketHandler].session)
}
override suspend fun login(configuration: BotNetworkConfiguration): LoginResult {
override suspend fun login(configuration: BotNetworkConfiguration): LoginResult = withContext(this.coroutineContext) {
TIMProtocol.SERVER_IP.forEach {
bot.logger.logInfo("Connecting server $it")
this.socket = BotSocketAdapter(it, configuration)
socket = BotSocketAdapter(it, configuration)
loginResult = CompletableDeferred()
val state = socket.resendTouch()
if (state != LoginResult.TIMEOUT) {
return state
return@withContext state
}
bot.logger.logPurple("Timeout. Retrying next server")
socket.close()
}
return LoginResult.TIMEOUT
return@withContext LoginResult.TIMEOUT
}
internal var loginResult: CompletableDeferred<LoginResult> = CompletableDeferred()
@ -156,7 +157,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
loginHandler = LoginHandler(configuration)
val expect = expectPacket<ServerTouchResponsePacket>()
val expect = expectPacket<TouchResponsePacket>()
launch { processReceive() }
launch {
if (withTimeoutOrNull(configuration.touchTimeout.millisecondsLong) { expect.join() } == null) {
@ -240,11 +241,11 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
}
}*/
override suspend fun sendPacket(packet: OutgoingPacket): Unit = coroutineScope {
override suspend fun sendPacket(packet: OutgoingPacket): Unit = withContext(coroutineContext) {
check(channel.isOpen) { "channel is not open" }
if (BeforePacketSendEvent(bot, packet).broadcast().cancelled) {
return@coroutineScope
return@withContext
}
packet.packet.use { build ->
@ -255,7 +256,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
} catch (e: SendPacketInternalException) {
bot.logger.logError("Caught SendPacketInternalException: ${e.cause?.message}")
bot.reinitializeNetworkHandler(configuration, e)
return@coroutineScope
return@withContext
} finally {
buffer.release(IoBuffer.Pool)
}
@ -294,6 +295,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
private var captchaSectionId: Int = 1
private var captchaCache: IoBuffer? = null
//set 为 null 时自动 release; get 为 null 时自动 borrow
get() {
if (field == null) field = IoBuffer.Pool.borrow()
return field
@ -307,7 +309,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
suspend fun onPacketReceived(packet: ServerPacket) {
when (packet) {
is ServerTouchResponsePacket -> {
is TouchResponsePacket -> {
if (packet.serverIP != null) {//redirection
socket.close()
socket = BotSocketAdapter(packet.serverIP!!, socket.configuration)
@ -319,7 +321,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
this.token0825 = packet.token0825
socket.sendPacket(
OutgoingPasswordSubmissionPacket(
SubmitPasswordPacket(
bot = bot.qqAccount,
password = bot.account.password,
loginTime = loginTime,
@ -333,17 +335,17 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
}
}
is ServerLoginResponseFailedPacket -> {
is LoginResponseFailedPacket -> {
loginResult.complete(packet.loginResult)
return
}
is ServerCaptchaCorrectPacket -> {
is CaptchaCorrectPacket -> {
this.privateKey = getRandomByteArray(16)//似乎是必须的
this.token00BA = packet.token00BA
socket.sendPacket(
OutgoingPasswordSubmissionPacket(
SubmitPasswordPacket(
bot = bot.qqAccount,
password = bot.account.password,
loginTime = loginTime,
@ -356,7 +358,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
)
}
is ServerLoginResponseCaptchaInitPacket -> {
is LoginResponseCaptchaInitPacket -> {
//[token00BA]来源之一: 验证码
this.token00BA = packet.token00BA
this.captchaCache = packet.captchaPart1
@ -364,7 +366,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
if (packet.unknownBoolean) {
this.captchaSectionId = 1
socket.sendPacket(
OutgoingCaptchaTransmissionRequestPacket(
RequestCaptchaTransmissionPacket(
bot.qqAccount,
this.token0825,
this.captchaSectionId++,
@ -374,7 +376,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
}
}
is ServerCaptchaTransmissionPacket -> {
is CaptchaTransmissionResponsePacket -> {
//packet is ServerCaptchaWrongPacket
if (this.captchaSectionId == 0) {
bot.logger.logPurple("验证码错误, 请重新输入")
@ -395,7 +397,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
} else {
this.captchaSectionId = 0//意味着已经提交验证码
socket.sendPacket(
OutgoingCaptchaSubmitPacket(
SubmitCaptchaPacket(
bot.qqAccount,
token0825,
code,
@ -405,7 +407,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
}
} else {
socket.sendPacket(
OutgoingCaptchaTransmissionRequestPacket(
RequestCaptchaTransmissionPacket(
bot.qqAccount,
token0825,
captchaSectionId++,
@ -415,10 +417,10 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
}
}
is ServerLoginResponseSuccessPacket -> {
is LoginResponseSuccessPacket -> {
this.sessionResponseDecryptionKey = packet.sessionResponseDecryptionKey
socket.sendPacket(
OutgoingSessionRequestPacket(
RequestSessionPacket(
bot.qqAccount,
socket.serverIp,
packet.token38,
@ -429,11 +431,11 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
}
//是ClientPasswordSubmissionPacket之后服务器回复的可能之一
is ServerLoginResponseKeyExchangePacket -> {
is LoginResponseKeyExchangeResponsePacket -> {
this.privateKey = packet.privateKeyUpdate
socket.sendPacket(
OutgoingPasswordSubmissionPacket(
SubmitPasswordPacket(
bot = bot.qqAccount,
password = bot.account.password,
loginTime = loginTime,
@ -447,7 +449,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
)
}
is ServerSessionKeyResponsePacket -> {
is SessionKeyResponsePacket -> {
sessionKey = packet.sessionKey
bot.logger.logPurple("sessionKey = ${sessionKey.toUHexString()}")
@ -485,11 +487,11 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
is ServerCaptchaPacket.Encrypted -> socket.distributePacket(packet.decrypt())
is ServerLoginResponseCaptchaInitPacket.Encrypted -> socket.distributePacket(packet.decrypt())
is ServerLoginResponseKeyExchangePacket.Encrypted -> socket.distributePacket(packet.decrypt(this.privateKey))
is ServerLoginResponseSuccessPacket.Encrypted -> socket.distributePacket(packet.decrypt(this.privateKey))
is ServerSessionKeyResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt(this.sessionResponseDecryptionKey))
is ServerTouchResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt())
is LoginResponseCaptchaInitPacket.Encrypted -> socket.distributePacket(packet.decrypt())
is LoginResponseKeyExchangeResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt(this.privateKey))
is LoginResponseSuccessPacket.Encrypted -> socket.distributePacket(packet.decrypt(this.privateKey))
is SessionKeyResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt(this.sessionResponseDecryptionKey))
is TouchResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt())
is UnknownServerPacket.Encrypted -> socket.distributePacket(packet.decrypt(sessionKey))
else -> {

View File

@ -15,6 +15,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.event.ServerEventPacket
import net.mamoe.mirai.network.protocol.tim.packet.login.RequestSKeyPacket
import net.mamoe.mirai.network.qqAccount
import net.mamoe.mirai.utils.log
import kotlin.coroutines.CoroutineContext
/**
* 动作: 获取好友列表, 点赞, 踢人等.
@ -23,6 +24,9 @@ import net.mamoe.mirai.utils.log
* @author Him188moe
*/
class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
override val coroutineContext: CoroutineContext
get() = session.NetworkScope.coroutineContext
companion object Key : PacketHandler.Key<ActionPacketHandler>
@ -66,15 +70,15 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
}
}
suspend fun requestSKey() = with(session) {
withContext(NetworkScope.coroutineContext) {
private suspend fun requestSKey() = with(session) {
withContext(coroutineContext) {
socket.sendPacket(RequestSKeyPacket())
}
}
suspend fun requestAccountInfo() = with(session) {
withContext(NetworkScope.coroutineContext) {
withContext(coroutineContext) {
socket.sendPacket(RequestAccountInfoPacket(qqAccount, sessionKey))
}
}

View File

@ -1,5 +1,6 @@
package net.mamoe.mirai.network.protocol.tim.handler
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.network.BotSession
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import kotlin.reflect.KClass
@ -9,7 +10,7 @@ import kotlin.reflect.KClass
*/
abstract class PacketHandler(
val session: BotSession
) {
) : CoroutineScope {
abstract suspend fun onPacketReceived(packet: ServerPacket)
interface Key<T : PacketHandler>
@ -19,18 +20,18 @@ abstract class PacketHandler(
}
}
class PacketHandlerNode<T : PacketHandler>(
internal class PacketHandlerNode<T : PacketHandler>(
val clazz: KClass<T>,
val instance: T,
val key: PacketHandler.Key<T>
)
fun <T : PacketHandler> T.asNode(key: PacketHandler.Key<T>): PacketHandlerNode<T> {
internal fun <T : PacketHandler> T.asNode(key: PacketHandler.Key<T>): PacketHandlerNode<T> {
@Suppress("UNCHECKED_CAST")
return PacketHandlerNode(this::class as KClass<T>, this, key)
}
open class PacketHandlerList : MutableList<PacketHandlerNode<*>> by mutableListOf() {
internal open class PacketHandlerList : MutableList<PacketHandlerNode<*>> by mutableListOf() {
@Suppress("UNCHECKED_CAST")
operator fun <T : PacketHandler> get(key: PacketHandler.Key<T>): T = this.first { it.key === key }.instance as T
}

View File

@ -6,9 +6,9 @@ import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.writeUByte
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.utils.encryptAndWrite
import net.mamoe.mirai.utils.writeHex
import net.mamoe.mirai.utils.writeQQ
import net.mamoe.mirai.utils.io.encryptAndWrite
import net.mamoe.mirai.utils.io.writeHex
import net.mamoe.mirai.utils.io.writeQQ
/**
* 获取升级天数等.

View File

@ -5,9 +5,9 @@ package net.mamoe.mirai.network.protocol.tim.packet
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.utils.encryptAndWrite
import net.mamoe.mirai.utils.writeHex
import net.mamoe.mirai.utils.writeQQ
import net.mamoe.mirai.utils.io.encryptAndWrite
import net.mamoe.mirai.utils.io.writeHex
import net.mamoe.mirai.utils.io.writeQQ
@PacketId(0x00_58u)
class HeartbeatPacket(

View File

@ -5,7 +5,7 @@ package net.mamoe.mirai.network.protocol.tim.packet
import kotlinx.atomicfu.atomic
import kotlinx.io.core.*
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.utils.writeHex
import net.mamoe.mirai.utils.io.writeHex
/**
* 发给服务器的数据包. 必须有 [PacketId] 注解或 `override` [id]. 否则将会抛出 [IllegalStateException]

View File

@ -4,8 +4,8 @@ package net.mamoe.mirai.network.protocol.tim.packet
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.writeFully
import net.mamoe.mirai.utils.encryptAndWrite
import net.mamoe.mirai.utils.writeQQ
import net.mamoe.mirai.utils.io.encryptAndWrite
import net.mamoe.mirai.utils.io.writeQQ
class OutgoingRawPacket(
override val id: UShort,

View File

@ -4,11 +4,14 @@ package net.mamoe.mirai.network.protocol.tim.packet
import kotlinx.io.core.*
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.GroupInternalId
import net.mamoe.mirai.network.session
import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.read
import net.mamoe.mirai.utils.io.toUHexString
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.hexToBytes
import net.mamoe.mirai.utils.httpPostGroupImage
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.readUnsignedVarInt
suspend fun Group.uploadImage(
@ -19,7 +22,7 @@ suspend fun Group.uploadImage(
if (it.uKey != null) {
httpPostGroupImage(
botAccount = bot.qqAccount,
groupNumber = internalId,
groupInternalId = internalId,
imageInput = image.input,
inputSize = image.inputSize,
uKeyHex = it.uKey!!.toUHexString("")
@ -35,7 +38,7 @@ suspend fun Group.uploadImage(
@PacketVersion(date = "2019.10.20", timVersion = "2.3.2.21173")
class GroupImageIdRequestPacket(
private val bot: UInt,
private val groupId: UInt,
private val groupInternalId: GroupInternalId,
private val image: ExternalImage,
private val sessionKey: ByteArray
) : OutgoingPacket() {
@ -146,7 +149,7 @@ class GroupImageIdRequestPacket(
writeHex("01 12 03 98 01 01 10 01 1A")
writeUVarintLVPacket(lengthOffset = { it + 1 }) {
writeTUVarint(0x08u, groupId)
writeTUVarint(0x08u, groupInternalId.value)
writeTUVarint(0x10u, bot)
writeTV(0x1800u)

View File

@ -8,9 +8,9 @@ import kotlinx.io.core.discardExact
import kotlinx.io.core.readUShort
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.*
import net.mamoe.mirai.utils.encryptAndWrite
import net.mamoe.mirai.utils.writeHex
import net.mamoe.mirai.utils.writeQQ
import net.mamoe.mirai.utils.io.encryptAndWrite
import net.mamoe.mirai.utils.io.writeHex
import net.mamoe.mirai.utils.io.writeQQ
/**
* 向服务器检查是否可添加某人为好友

View File

@ -12,8 +12,8 @@ import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket
import net.mamoe.mirai.network.protocol.tim.packet.PacketId
import net.mamoe.mirai.network.protocol.tim.packet.PacketVersion
import net.mamoe.mirai.network.protocol.tim.packet.ResponsePacket
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.toUHexString
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.md5
fun main() {
println("牛逼".toMessage().toChain().toPacket(true).readBytes().toUHexString())

View File

@ -4,29 +4,30 @@ package net.mamoe.mirai.network.protocol.tim.packet.action
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.contact.GroupInternalId
import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.message.internal.toPacket
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket
import net.mamoe.mirai.network.protocol.tim.packet.PacketId
import net.mamoe.mirai.network.protocol.tim.packet.ResponsePacket
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.*
@PacketId(0x00_02u)
class SendGroupMessagePacket(
private val botQQ: UInt,
private val groupId: UInt,//不是 number
private val sessionKey: ByteArray,
private val message: MessageChain
private val botQQ: UInt,
private val groupInternalId: GroupInternalId,
private val sessionKey: ByteArray,
private val message: MessageChain
) : OutgoingPacket() {
override fun encode(builder: BytePacketBuilder) = with(builder) {
this.writeQQ(botQQ)
this.writeHex(TIMProtocol.fixVer2)
writeQQ(botQQ)
writeHex(TIMProtocol.fixVer2)
this.encryptAndWrite(sessionKey) {
encryptAndWrite(sessionKey) {
writeByte(0x2A)
writeGroup(groupId)
writeGroup(groupInternalId)
writeShortLVPacket {
writeHex("00 01 01")

View File

@ -26,7 +26,7 @@ class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventP
* 发送方权限.
*/
lateinit var senderPermission: SenderPermission
lateinit var message: MessageChain
var message: MessageChain by Delegates.notNull()
override fun decode() = with(input) {
discardExact(31)
@ -95,7 +95,7 @@ class ServerFriendMessageEventPacket(input: ByteReadPacket, eventIdentity: Event
*/
var isPrevious: Boolean = false
lateinit var message: MessageChain
var message: MessageChain by Delegates.notNull()
//来自自己发送给自己
//00 00 00 20 00 05 00 02 00 06 00 06 00 04 00 01 01 07 00 09 00 06 03 E9 20 02 EB 94 00 0A 00 04 01 00 00 00 0C 17 76 E4 B8 DD 76 E4 B8 DD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B A6 D2 5D A3 2A 3F 00 00 5D A3 2A 3F 01 00 00 00 00 4D 53 47 00 00 00 00 00 5D A3 2A 3F 0C 8A 59 3D 00 00 00 00 0A 00 86 02 00 06 E5 AE 8B E4 BD 93 00 00 01 00 06 01 00 03 31 32 33 19 00 1F 01 00 1C AA 02 19 08 00 88 01 00 9A 01 11 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 0E 00 0E 01 00 04 00 00 00 00 0A 00 04 00 00 00 00

View File

@ -8,10 +8,9 @@ import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import net.mamoe.mirai.network.protocol.tim.packet.applySequence
import net.mamoe.mirai.network.protocol.tim.packet.decryptBy
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.readBoolean
import net.mamoe.mirai.utils.io.readIoBuffer
import net.mamoe.mirai.utils.io.toUHexString
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.toByteArray
/**
* 事件的识别 ID. [事件确认包][ServerEventPacket.ResponsePacket] 中被使用.

View File

@ -6,25 +6,21 @@ import kotlinx.io.core.*
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.*
import net.mamoe.mirai.utils.Tested
import net.mamoe.mirai.utils.encryptAndWrite
import net.mamoe.mirai.utils.io.readIoBuffer
import net.mamoe.mirai.utils.io.toReadPacket
import net.mamoe.mirai.utils.writeHex
import net.mamoe.mirai.utils.writeQQ
import net.mamoe.mirai.utils.io.*
/**
* 客户端请求验证码图片数据的第几部分
*/
@PacketId(0x00_BAu)
class OutgoingCaptchaTransmissionRequestPacket(
private val qq: UInt,
private val token0825: ByteArray,
private val verificationSequence: Int,
private val token00BA: ByteArray
class RequestCaptchaTransmissionPacket(
private val bot: UInt,
private val token0825: ByteArray,
private val verificationSequence: Int,
private val token00BA: ByteArray
) : OutgoingPacket() {
@Tested
override fun encode(builder: BytePacketBuilder) = with(builder) {
this.writeQQ(qq)
this.writeQQ(bot)
this.writeHex(TIMProtocol.fixVer)
this.writeHex(TIMProtocol.key00BA)
this.encryptAndWrite(TIMProtocol.key00BA) {
@ -48,18 +44,18 @@ class OutgoingCaptchaTransmissionRequestPacket(
* 提交验证码
*/
@PacketId(0x00_BAu)
class OutgoingCaptchaSubmitPacket(
private val qq: UInt,
private val token0825: ByteArray,
private val captcha: String,
private val verificationToken: IoBuffer
class SubmitCaptchaPacket(
private val bot: UInt,
private val token0825: ByteArray,
private val captcha: String,
private val verificationToken: IoBuffer
) : OutgoingPacket() {
init {
require(captcha.length == 4) { "captcha.length must == 4" }
}
override fun encode(builder: BytePacketBuilder) = with(builder) {
this.writeQQ(qq)
this.writeQQ(bot)
this.writeHex(TIMProtocol.fixVer)
this.writeHex(TIMProtocol.key00BA)
this.encryptAndWrite(TIMProtocol.key00BA) {
@ -114,7 +110,7 @@ class OutgoingCaptchaRefreshPacket(
* @author Him188moe
*/
@PacketId(0x00_BAu)
open class ServerCaptchaTransmissionPacket(input: ByteReadPacket) : ServerCaptchaPacket(input) {
open class CaptchaTransmissionResponsePacket(input: ByteReadPacket) : ServerCaptchaPacket(input) {
lateinit var captchaSectionN: IoBuffer
lateinit var verificationToken: IoBuffer//56bytes
@ -141,7 +137,7 @@ open class ServerCaptchaTransmissionPacket(input: ByteReadPacket) : ServerCaptch
/*
fun main() {
val data = "13 00 05 01 00 00 01 23 00 38 59 32 29 5A 3E 3D 2D FC F5 22 EB 9E 2D FB 9C 4F AA 06 C8 32 3D F0 3C 2C 2B BA 8D 05 C4 9B C1 74 3B 70 F1 99 90 BB 6E 3E 6F 74 48 97 D3 61 B7 04 C0 A3 F1 DF 40 A4 DC 2B 00 A2 01 2D BB BB E8 FE B8 AF B3 6F 39 7C EA E2 5B 91 BE DB 59 38 CF 58 BC F2 88 F1 09 CF 92 E9 F7 FB 13 76 C5 68 29 23 3F 8E 43 16 2E 50 D7 FA 4D C1 F7 67 EF 27 FB C6 F1 A7 25 A4 BC 45 39 3A EA B2 A5 38 02 FF 4B C9 FF EB BD 89 E5 5D B9 4A 2A BE 5F 52 F1 EB 09 29 CB 3E 66 CF EF 97 89 47 BB 6B E0 7B 4A 3E A1 BC 3F FB F2 0A 83 CB E3 EA B9 43 E1 26 88 03 0B A7 E0 B2 AD 7F 83 CC DA 74 85 83 72 08 EC D2 F9 95 05 15 05 96 F7 1C FF 00 82 C3 90 22 A4 BA 90 D5 00 00 00 00 49 45 4E 44 AE 42 60 82 03 00 00 28 EA 32 5A 85 C8 D2 73 B3 40 39 77 85 65 98 00 FE 03 A2 A5 95 B4 2F E6 79 7A DE 5A 03 10 C8 3D BF 6D 3D 8B 51 84 C2 6D 49 00 10 92 AA 69 FB C6 3D 60 5A 7A A4 AC 7A B0 71 00 36".hexToBytes()
ServerCaptchaTransmissionPacket(data.toReadPacket(), data.size, "00 BA 31 01".hexToBytes()).let {
CaptchaTransmissionResponsePacket(data.toReadPacket(), data.size, "00 BA 31 01".hexToBytes()).let {
it.dataDecode()
println(it.toString())
}
@ -153,7 +149,7 @@ fun main() {
* @author Him188moe
*/
@PacketId(0x00_BAu)
class ServerCaptchaCorrectPacket(input: ByteReadPacket) : ServerCaptchaPacket(input) {
class CaptchaCorrectPacket(input: ByteReadPacket) : ServerCaptchaPacket(input) {
lateinit var token00BA: ByteArray//56 bytes
override fun decode() = with(input) {
@ -172,9 +168,9 @@ abstract class ServerCaptchaPacket(input: ByteReadPacket) : ServerPacket(input)
return when (data.size) {
66,
95 -> ServerCaptchaCorrectPacket(data.toReadPacket())
95 -> CaptchaCorrectPacket(data.toReadPacket())
//66 -> ServerCaptchaUnknownPacket(data.toReadPacket())
else -> ServerCaptchaTransmissionPacket(data.toReadPacket())
else -> CaptchaTransmissionResponsePacket(data.toReadPacket())
}.applySequence(sequenceId)
}
}

View File

@ -8,9 +8,9 @@ import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket
import net.mamoe.mirai.network.protocol.tim.packet.PacketId
import net.mamoe.mirai.utils.OnlineStatus
import net.mamoe.mirai.utils.encryptAndWrite
import net.mamoe.mirai.utils.writeHex
import net.mamoe.mirai.utils.writeQQ
import net.mamoe.mirai.utils.io.encryptAndWrite
import net.mamoe.mirai.utils.io.writeHex
import net.mamoe.mirai.utils.io.writeQQ
/**
* 改变在线状态: "我在线上", "隐身"

View File

@ -8,14 +8,17 @@ import kotlinx.io.core.writeFully
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket
import net.mamoe.mirai.network.protocol.tim.packet.PacketId
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.TEA
import net.mamoe.mirai.utils.hexToBytes
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.writeCRC32
/**
* 提交密码
*/
@PacketId(0x08_36u)
class OutgoingPasswordSubmissionPacket constructor(
class SubmitPasswordPacket constructor(
private val bot: UInt,
private val password: String,
private val loginTime: Int,

View File

@ -1,4 +1,4 @@
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE")
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE", "FunctionName")
package net.mamoe.mirai.network.protocol.tim.packet.login
@ -11,13 +11,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket
import net.mamoe.mirai.network.protocol.tim.packet.PacketId
import net.mamoe.mirai.network.protocol.tim.packet.ResponsePacket
import net.mamoe.mirai.network.qqAccount
import net.mamoe.mirai.utils.encryptAndWrite
import net.mamoe.mirai.utils.io.DebugLogger
import net.mamoe.mirai.utils.io.readRemainingBytes
import net.mamoe.mirai.utils.io.readString
import net.mamoe.mirai.utils.io.toUHexString
import net.mamoe.mirai.utils.writeHex
import net.mamoe.mirai.utils.writeQQ
import net.mamoe.mirai.utils.io.*
fun BotSession.RequestSKeyPacket() = RequestSKeyPacket(qqAccount, sessionKey)
@ -27,11 +21,11 @@ fun BotSession.RequestSKeyPacket() = RequestSKeyPacket(qqAccount, sessionKey)
*/
@PacketId(0x00_1Du)
class RequestSKeyPacket(
private val qq: UInt,
private val sessionKey: ByteArray
private val bot: UInt,
private val sessionKey: ByteArray
) : OutgoingPacket() {
override fun encode(builder: BytePacketBuilder) = with(builder) {
writeQQ(qq)
writeQQ(bot)
writeHex(TIMProtocol.fixVer2)
encryptAndWrite(sessionKey) {
writeHex("33 00 05 00 08 74 2E 71 71 2E 63 6F 6D 00 0A 71 75 6E 2E 71 71 2E 63 6F 6D 00 0C 71 7A 6F 6E 65 2E 71 71 2E 63 6F 6D 00 0C 6A 75 62 61 6F 2E 71 71 2E 63 6F 6D 00 09 6B 65 2E 71 71 2E 63 6F 6D")

View File

@ -16,13 +16,13 @@ import kotlin.properties.Delegates
sealed class ServerLoginResponsePacket(input: ByteReadPacket) : ServerPacket(input)
@PacketId(0x08_36u)
class ServerLoginResponseFailedPacket(val loginResult: LoginResult, input: ByteReadPacket) : ServerLoginResponsePacket(input)
class LoginResponseFailedPacket(val loginResult: LoginResult, input: ByteReadPacket) : ServerLoginResponsePacket(input)
/**
* 服务器进行加密后返回 privateKey
*/
@PacketId(0x08_36u)
class ServerLoginResponseKeyExchangePacket(input: ByteReadPacket) : ServerLoginResponsePacket(input) {
class LoginResponseKeyExchangeResponsePacket(input: ByteReadPacket) : ServerLoginResponsePacket(input) {
lateinit var tlv0006: IoBuffer//120bytes
var tokenUnknown: ByteArray? = null
@ -47,7 +47,8 @@ class ServerLoginResponseKeyExchangePacket(input: ByteReadPacket) : ServerLoginR
@PacketId(0x08_36u)
class Encrypted(input: ByteReadPacket) : ServerPacket(input) {
@Tested
fun decrypt(privateKey: ByteArray): ServerLoginResponseKeyExchangePacket = ServerLoginResponseKeyExchangePacket(this.decryptBy(TIMProtocol.shareKey, privateKey)).applySequence(sequenceId)
fun decrypt(privateKey: ByteArray): LoginResponseKeyExchangeResponsePacket =
LoginResponseKeyExchangeResponsePacket(this.decryptBy(TIMProtocol.shareKey, privateKey)).applySequence(sequenceId)
}
}
@ -60,7 +61,7 @@ enum class Gender(val id: Boolean) {
* @author NaturalHG
*/
@PacketId(0x08_36u)
class ServerLoginResponseSuccessPacket(input: ByteReadPacket) : ServerLoginResponsePacket(input) {
class LoginResponseSuccessPacket(input: ByteReadPacket) : ServerLoginResponsePacket(input) {
lateinit var sessionResponseDecryptionKey: IoBuffer//16 bytes|
lateinit var token38: IoBuffer//56
@ -116,7 +117,7 @@ class ServerLoginResponseSuccessPacket(input: ByteReadPacket) : ServerLoginRespo
@PacketId(0x08_36u)
class Encrypted(input: ByteReadPacket) : ServerPacket(input) {
fun decrypt(privateKey: ByteArray): ServerLoginResponseSuccessPacket = ServerLoginResponseSuccessPacket(this.decryptBy(TIMProtocol.shareKey, privateKey)).applySequence(sequenceId)
fun decrypt(privateKey: ByteArray): LoginResponseSuccessPacket = LoginResponseSuccessPacket(this.decryptBy(TIMProtocol.shareKey, privateKey)).applySequence(sequenceId)
}
}
@ -127,7 +128,7 @@ class ServerLoginResponseSuccessPacket(input: ByteReadPacket) : ServerLoginRespo
* @author Him188moe
*/
@PacketId(0x08_36u)
class ServerLoginResponseCaptchaInitPacket(input: ByteReadPacket) : ServerLoginResponsePacket(input) {
class LoginResponseCaptchaInitPacket(input: ByteReadPacket) : ServerLoginResponsePacket(input) {
lateinit var captchaPart1: IoBuffer
lateinit var token00BA: ByteArray
@ -152,6 +153,6 @@ class ServerLoginResponseCaptchaInitPacket(input: ByteReadPacket) : ServerLoginR
@PacketId(0x08_36u)
class Encrypted(input: ByteReadPacket) : ServerPacket(input) {
fun decrypt(): ServerLoginResponseCaptchaInitPacket = ServerLoginResponseCaptchaInitPacket(decryptAsByteArray(TIMProtocol.shareKey).toReadPacket()).applySequence(sequenceId)
fun decrypt(): LoginResponseCaptchaInitPacket = LoginResponseCaptchaInitPacket(decryptAsByteArray(TIMProtocol.shareKey).toReadPacket()).applySequence(sequenceId)
}
}

View File

@ -5,11 +5,12 @@ package net.mamoe.mirai.network.protocol.tim.packet.login
import kotlinx.io.core.*
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.*
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.readIoBuffer
import net.mamoe.mirai.utils.Tested
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.localIpAddress
@PacketId(0x08_28u)
class OutgoingSessionRequestPacket(
class RequestSessionPacket(
private val bot: UInt,
private val serverIp: String,
private val token38: IoBuffer,
@ -61,7 +62,7 @@ class OutgoingSessionRequestPacket(
@PacketId(0x08_28u)
class ServerSessionKeyResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
class SessionKeyResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
lateinit var sessionKey: ByteArray
lateinit var tlv0105: ByteReadPacket
@ -111,7 +112,7 @@ Discarded(11) =41 01 00 02 03 3C 01 03 00 00 86
@PacketId(0x08_28u)
class Encrypted(input: ByteReadPacket) : ServerPacket(input) {
fun decrypt(sessionResponseDecryptionKey: IoBuffer): ServerSessionKeyResponsePacket =
ServerSessionKeyResponsePacket(decryptBy(sessionResponseDecryptionKey)).applySequence(sequenceId)
fun decrypt(sessionResponseDecryptionKey: IoBuffer): SessionKeyResponsePacket =
SessionKeyResponsePacket(decryptBy(sessionResponseDecryptionKey)).applySequence(sequenceId)
}
}

View File

@ -8,20 +8,21 @@ import kotlinx.io.core.discardExact
import kotlinx.io.core.readBytes
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.*
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.readIP
import net.mamoe.mirai.utils.hexToBytes
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.toUHexString
/**
* The packet received when logging in, used to redirect server address
*
* @see OutgoingTouchRedirectionPacket
* @see OutgoingPasswordSubmissionPacket
* @see SubmitPasswordPacket
*
* @author Him188moe
*/
@Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
@PacketId(0x08_25u)
class ServerTouchResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
class TouchResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
var serverIP: String? = null
var loginTime: Int = 0
@ -51,7 +52,7 @@ class ServerTouchResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
@PacketId(0x08_25u)
class Encrypted(input: ByteReadPacket) : ServerPacket(input) {
fun decrypt(): ServerTouchResponsePacket = ServerTouchResponsePacket(decryptBy(TIMProtocol.touchKey.hexToBytes())).applySequence(sequenceId)
fun decrypt(): TouchResponsePacket = TouchResponsePacket(decryptBy(TIMProtocol.touchKey.hexToBytes())).applySequence(sequenceId)
}
}

View File

@ -2,37 +2,39 @@ package net.mamoe.mirai.utils
import com.soywiz.klock.TimeSpan
import com.soywiz.klock.seconds
import net.mamoe.mirai.network.protocol.tim.packet.login.ServerTouchResponsePacket
import net.mamoe.mirai.network.protocol.tim.packet.login.TouchResponsePacket
import kotlin.jvm.JvmField
import kotlin.jvm.JvmOverloads
/**
* 网络配置
*/
class BotNetworkConfiguration {
class BotNetworkConfiguration @JvmOverloads constructor(
/**
* 等待 [ServerTouchResponsePacket] 的时间
* 等待 [TouchResponsePacket] 的时间
*/
var touchTimeout: TimeSpan = 2.seconds
var touchTimeout: TimeSpan = 2.seconds,
/**
* 是否使用随机的设备名.
* 使用随机可以降低被封禁的风险, 但可能导致每次登录都需要输入验证码
* 当一台设备只登录少量账号时, 将此项设置为 `true` 可能更好.
*/
var randomDeviceName: Boolean = false
var randomDeviceName: Boolean = false,
/**
* 心跳周期. 过长会导致被服务器断开连接.
*/
var heartbeatPeriod: TimeSpan = 60.seconds
var heartbeatPeriod: TimeSpan = 60.seconds,
/**
* 每次心跳时等待结果的时间.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 1s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响.
*/
var heartbeatTimeout: TimeSpan = 2.seconds
) {
companion object {
/**
* 默认的配置实例
*/
@JvmField
val Default = BotNetworkConfiguration()
}

View File

@ -10,6 +10,7 @@ import io.ktor.http.HttpStatusCode
import io.ktor.http.URLProtocol
import io.ktor.http.userAgent
import kotlinx.io.core.Input
import net.mamoe.mirai.contact.GroupInternalId
/**
* 时间戳
@ -72,7 +73,7 @@ suspend fun httpPostFriendImage(
@Suppress("DuplicatedCode")
suspend fun httpPostGroupImage(
botAccount: UInt,
groupNumber: UInt,
groupInternalId: GroupInternalId,
uKeyHex: String,
imageInput: Input,
inputSize: Long
@ -80,7 +81,7 @@ suspend fun httpPostGroupImage(
url {
parameters["htcmd"] = "0x6ff0071"
parameters["uin"] = botAccount.toLong().toString()
parameters["groupcode"] = groupNumber.toLong().toString()
parameters["groupcode"] = groupInternalId.value.toLong().toString()
}
} as HttpStatusCode).value.also { println(it) } == 200

View File

@ -1,6 +1,6 @@
@file:JvmName("IterableUtil")
package net.mamoe.mirai.utils
package net.mamoe.mirai.utils.internal
import kotlin.jvm.JvmName

View File

@ -33,18 +33,19 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {
discardExact(7)//4 for qq number, 3 for 0x00 0x00 0x00. 但更可能是应该 discard 8
return when (id.toUInt()) {
0x08_25u -> ServerTouchResponsePacket.Encrypted(this)
0x08_25u -> TouchResponsePacket.Encrypted(this)
0x08_36u -> {
//todo 不要用size分析
when (size) {
271, 207 -> return ServerLoginResponseKeyExchangePacket.Encrypted(this).applySequence(sequenceId)
871 -> return ServerLoginResponseCaptchaInitPacket.Encrypted(this).applySequence(sequenceId)
271, 207 -> return LoginResponseKeyExchangeResponsePacket.Encrypted(this).applySequence(sequenceId)
871 -> return LoginResponseCaptchaInitPacket.Encrypted(this).applySequence(sequenceId)
}
if (size > 700) return ServerLoginResponseSuccessPacket.Encrypted(this).applySequence(sequenceId)
if (size > 700) return LoginResponseSuccessPacket.Encrypted(this).applySequence(sequenceId)
println("登录包size=$size")
return ServerLoginResponseFailedPacket(when (size) {
return LoginResponseFailedPacket(
when (size) {
135 -> {//包数据错误. 目前怀疑是 tlv0006
this.readRemainingBytes().cutTail(1).decryptBy(TIMProtocol.shareKey).read {
discardExact(51)
@ -70,7 +71,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {
else -> throw IllegalArgumentException(bytes.size.toString())*/
}, this).applySequence(sequenceId)
}
0x08_28u -> ServerSessionKeyResponsePacket.Encrypted(this)
0x08_28u -> SessionKeyResponsePacket.Encrypted(this)
0x00_ECu -> ServerLoginSuccessPacket(this)
0x00_BAu -> ServerCaptchaPacket.Encrypted(this)

View File

@ -1,9 +1,12 @@
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.utils
package net.mamoe.mirai.utils.io
import kotlinx.io.core.*
import net.mamoe.mirai.contact.GroupId
import net.mamoe.mirai.contact.GroupInternalId
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.utils.*
import kotlin.random.Random
import kotlin.random.nextInt
@ -14,9 +17,8 @@ fun BytePacketBuilder.writeRandom(length: Int) = repeat(length) { this.writeByte
fun BytePacketBuilder.writeQQ(qq: Long) = this.writeUInt(qq.toUInt())
fun BytePacketBuilder.writeQQ(qq: UInt) = this.writeUInt(qq)
fun BytePacketBuilder.writeGroup(groupIdOrGroupNumber: Long) = this.writeUInt(groupIdOrGroupNumber.toUInt())
fun BytePacketBuilder.writeGroup(groupIdOrGroupNumber: UInt) = this.writeUInt(groupIdOrGroupNumber)
fun BytePacketBuilder.writeGroup(groupId: GroupId) = this.writeUInt(groupId.value)
fun BytePacketBuilder.writeGroup(groupInternalId: GroupInternalId) = this.writeUInt(groupInternalId.value)
fun BytePacketBuilder.writeShortLVByteArray(byteArray: ByteArray) {
this.writeShort(byteArray.size.toShort())
@ -98,7 +100,9 @@ fun BytePacketBuilder.writeTByteArray(tag: UByte, value: UByteArray) {
}
fun BytePacketBuilder.encryptAndWrite(key: IoBuffer, encoder: BytePacketBuilder.() -> Unit) = encryptAndWrite(key.readBytes(), encoder)
fun BytePacketBuilder.encryptAndWrite(key: ByteArray, encoder: BytePacketBuilder.() -> Unit) = writeFully(TEA.encrypt(BytePacketBuilder().apply(encoder).use { it.build().readBytes() }, key))
fun BytePacketBuilder.encryptAndWrite(key: ByteArray, encoder: BytePacketBuilder.() -> Unit) = writeFully(TEA.encrypt(BytePacketBuilder().apply(encoder).use {
it.build().readBytes()
}, key))
fun BytePacketBuilder.encryptAndWrite(keyHex: String, encoder: BytePacketBuilder.() -> Unit) = encryptAndWrite(keyHex.hexToBytes(), encoder)
fun BytePacketBuilder.writeTLV0006(qq: UInt, password: String, loginTime: Int, loginIP: String, privateKey: ByteArray) {

View File

@ -75,7 +75,7 @@ internal actual fun HttpRequestBuilder.configureBody(
override val contentType: ContentType = ContentType.Image.GIF
override val contentLength: Long = inputSize
override suspend fun writeTo(channel: ByteWriteChannel) {
override suspend fun writeTo(channel: ByteWriteChannel) {//不知道为什么这个 channel 在 common 找不到...
val buffer = byteArrayOf(1)
while (!input.endOfInput) {
input.readFully(buffer)

View File

@ -1,5 +1,7 @@
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS")
import net.mamoe.mirai.contact.groupId
import net.mamoe.mirai.contact.toInternalId
import net.mamoe.mirai.network.protocol.tim.packet.GroupImageIdRequestPacket
import net.mamoe.mirai.utils.hexToBytes
import net.mamoe.mirai.utils.io.readRemainingBytes
@ -15,9 +17,9 @@ fun main() = println({
// File("C:\\Users\\Him18\\Desktop\\test2.jpg").writeBytes(image.fileData.readBytes())
GroupImageIdRequestPacket(
1994701021u,
580266363u,
image,
sessionKey
1994701021u,
580266363u.groupId().toInternalId(),
image,
sessionKey
).packet.readRemainingBytes().toUHexString()
}())

View File

@ -2,7 +2,6 @@
package demo1
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeoutOrNull
import net.mamoe.mirai.Bot
@ -40,7 +39,7 @@ private fun readTestAccount(): BotAccount? {
}
@Suppress("UNUSED_VARIABLE")
suspend fun main() = coroutineScope {
suspend fun main() {
val bot = Bot(
readTestAccount() ?: BotAccount(//填写你的账号
id = 1994701121u,
@ -58,7 +57,7 @@ suspend fun main() = coroutineScope {
}
subscribeAlways<GroupMessageEvent> {
if (it.message eq "复读" && it.group.internalId == 580266363u) {
if (it.message eq "复读" && it.group.internalId.value == 580266363u) {
it.reply(it.message)
}
}