Support for approving friend add request

This commit is contained in:
Him188 2019-11-20 22:03:04 +08:00
parent 6cd7fb2411
commit 5e56144c61
15 changed files with 253 additions and 37 deletions

View File

@ -245,7 +245,7 @@ suspend fun ContactSystem.addFriend(id: UInt, lazyMessage: () -> String = { "" }
is CanAddFriendResponse.ReadyToAdd,
is CanAddFriendResponse.RequireVerification -> {
val key = RequestFriendAdditionKeyPacket(bot.qqAccount, id, sessionKey).sendAndExpect<RequestFriendAdditionKeyPacket.Response>().key
AddFriendPacket(bot.qqAccount, id, sessionKey, lazyMessage(), lazyRemark(), key).sendAndExpect<AddFriendPacket.Response>()
AddFriendPacket.RequestAdd(bot.qqAccount, id, sessionKey, lazyMessage(), lazyRemark(), key).sendAndExpect<AddFriendPacket.Response>()
return AddFriendResult.WAITING_FOR_APPROVE
}
//这个做的是需要验证消息的情况, 不确定 ReadyToAdd 的是啥

View File

@ -11,6 +11,7 @@ internal fun IoBuffer.parseMessageFace(): Face {
//00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D
discardExact(1)
// FIXME: 2019/11/20 EMOJI 表情会解析失败
val id1 = FaceId(readLVNumber().toInt().toUByte())//可能这个是id, 也可能下面那个
discardExact(readByte().toLong()) // -1
readLVNumber()//某id?

View File

@ -7,7 +7,6 @@ import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.utils.io.debugPrint
import net.mamoe.mirai.utils.io.encryptAndWrite
import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.writeQQ
@ -141,7 +140,7 @@ fun <T> PacketFactory<*, *>.buildSessionProtoPacket(
writeInt(head.size)
writeInt(proto.size)
writeFully(head)
writeFully(proto.debugPrint("proto data"))
writeFully(proto)
}
is String -> buildSessionProtoPacket(bot, sessionKey, name, id, sequenceId, headerSizeHint, version, head.hexToBytes(), serializer, protoObj)
}

View File

@ -4,10 +4,17 @@ package net.mamoe.mirai.network.protocol.tim.packet
import kotlinx.atomicfu.atomic
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
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.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
object PacketFactoryList : MutableList<PacketFactory<*, *>> by mutableListOf()
@ -43,6 +50,25 @@ 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): T {
val headLength = readInt()
val protoLength = readInt()
if (debuggingTag != null) {
readBytes(headLength).debugPrint("$debuggingTag head")
} else {
discardExact(headLength)
}
val bytes = readBytes(protoLength)
// println(ByteReadPacket(bytes).readProtoMap())
if (debuggingTag != null) {
bytes.read { readProtoMap() }.toString().debugPrint("$debuggingTag proto")
}
return ProtoBuf.load(deserializer, bytes)
}
companion object {
private val sequenceIdInternal = atomic(1)

View File

@ -81,6 +81,10 @@ enum class KnownPacketId(override inline val value: UShort, override inline val
inline REQUEST_PROFILE_DETAILS(0x003Cu, RequestProfileDetailsPacket),
inline QUERY_PREVIOUS_NAME(0x01BCu, QueryPreviousNamePacket),
// 031F 查询 "新朋友" 记录
// @Suppress("DEPRECATION")
// inline SUBMIT_IMAGE_FILE_NAME(0x01BDu, SubmitImageFilenamePacket),

View File

@ -5,6 +5,7 @@ package net.mamoe.mirai.network.protocol.tim.packet.action
import kotlinx.io.core.*
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.*
import net.mamoe.mirai.network.protocol.tim.packet.event.EventPacket
import net.mamoe.mirai.utils.io.*
@ -40,13 +41,17 @@ object QueryPreviousNamePacket : SessionPacketFactory<PreviousNameList>() {
// [00 00 00 10] 68 69 6D 31 38 38 E7 9A 84 E5 B0 8F 64 69 63 6B
// [00 00 00 0F] E4 B8 B6 E6 9A 97 E8 A3 94 E5 89 91 E9 AD 94
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): PreviousNameList =
PreviousNameList(ArrayList<String>(readUInt().toInt()).apply {
repeat(size) {
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): PreviousNameList {
// 00 00 00 01 00 00 00 0F E8 87 AA E5 8A A8 E9 A9 BE E9 A9 B6 31 2E 33
val count = readUInt().toInt()
return PreviousNameList(ArrayList<String>(count).apply {
repeat(count) {
discardExact(2)
add(readUShortLVString())
}
})
}
}
class PreviousNameList(
@ -192,9 +197,9 @@ object RequestFriendAdditionKeyPacket : SessionPacketFactory<RequestFriendAdditi
* 请求添加好友
*/
@AnnotatedId(KnownPacketId.ADD_FRIEND)
@PacketVersion(date = "2019.11.11", timVersion = "2.3.2 (21173)")
object AddFriendPacket : SessionPacketFactory<AddFriendPacket.Response>() {
operator fun invoke(
@PacketVersion(date = "2019.11.11", timVersion = "2.3.2 (21173)")
fun RequestAdd(
bot: UInt,
qq: UInt,
sessionKey: SessionKey,
@ -243,6 +248,53 @@ object AddFriendPacket : SessionPacketFactory<AddFriendPacket.Response>() {
// write
}
// 03 76 E4 B8 DD
// 00 00 09 //分组
// 00 29 //有备注
// 00 09 00 02 00 00 00 00
// [00 18] E8 87 AA E5 8A A8 E9 A9 BE E9 A9 B6 31 2E 33 E5 93 88 E5 93 88 E5 93 88
// [00 05] 00 00 00 00 01
// 03 76 E4 B8 DD
// 00 00 09 00 11 00 09 00 02 00 00 00 00 //没有备注, 选择分组和上面那个一样
// 00 00 00 05 00 00 00 00 01
// 03 76 E4 B8 DD
// 00 00 00
// 00 11 //没有备注
// 00 09 00 02 00 00 00 00
// 00 00 00 05 00 00 00 00 01
@PacketVersion(date = "2019.11.20", timVersion = "2.3.2 (21173)")
fun Approve(
bot: UInt,
sessionKey: SessionKey,
/**
* 好友列表分组的组的 ID. "我的好友" 0
*/
friendListId: Short,
qq: UInt,
/**
* 备注. 不设置则需要为 `null` TODO 需要确认是否还需发送一个设置备注包. 因为测试时若有备注则会多发一个包并且包里面有所设置的备注
*/
remark: String?
) = buildSessionPacket(bot, sessionKey, version = TIMProtocol.version0x02) {
writeByte(0x03)
writeQQ(qq)
writeZero(1)
writeUShort(friendListId.toUShort())
writeZero(1)
when (remark) {
null -> writeUByte(0x11u)
else -> writeUByte(0x29u)
}
writeHex("00 09 00 02 00 00 00 00")
when (remark) {
null -> writeZero(2)
else -> writeShortLVString(remark)
}
writeHex("00 05 00 00 00 00 01")
}
object Response : Packet {
override fun toString(): String = "AddFriendPacket.Response"
}

View File

@ -33,9 +33,7 @@ object RequestAccountInfoPacket : SessionPacketFactory<RequestAccountInfoPacket.
@NoLog
object Response : Packet {
//等级
//升级剩余活跃天数
//ignored
override fun toString(): String = "RequestAccountInfoPacket.Response"
}
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): Response = Response

View File

@ -4,11 +4,8 @@ package net.mamoe.mirai.network.protocol.tim.packet.action
import kotlinx.coroutines.withContext
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import kotlinx.io.core.readBytes
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.GroupId
import net.mamoe.mirai.contact.GroupInternalId
@ -23,7 +20,6 @@ import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.Http
import net.mamoe.mirai.utils.assertUnreachable
import net.mamoe.mirai.utils.io.debugPrintln
import net.mamoe.mirai.utils.io.toUHexString
import kotlin.coroutines.coroutineContext
@ -85,7 +81,7 @@ class ImageDownloadInfo(
val thumbnail: String get() = host + ":" + port.first() + _thumbnail!!
override val original: String get() = host + ":" + port.first() + _original!!
val compressed: String get() = host + ":" + port.first() + _compressed!!
override fun toString(): String = "ImageDownloadInfo(${_original?.let { original } ?: errorMessage ?: "unknown"}"
override fun toString(): String = "ImageDownloadInfo(${_original?.let { original } ?: errorMessage ?: "unknown"})"
}
fun ImageDownloadInfo.requireSuccess(): ImageDownloadInfo {
@ -224,11 +220,6 @@ object GroupImagePacket : SessionPacketFactory<GroupImageResponse>() {
}
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): GroupImageResponse {
val headLength = readInt()
val protoLength = readInt()
discardExact(headLength)
val bytes = readBytes(protoLength)
// println(ByteReadPacket(bytes).readProtoMap())
@Serializable
data class GroupImageResponseProto(
@ -236,8 +227,7 @@ object GroupImagePacket : SessionPacketFactory<GroupImageResponse>() {
@SerialId(4) val imageDownloadInfo: ImageDownloadInfo? = null
)
debugPrintln("收到返回=" + bytes.toUHexString())
val proto = ProtoBuf.load(GroupImageResponseProto.serializer(), bytes)
val proto = decodeProtoPacket(GroupImageResponseProto.serializer())
return when {
proto.imageUploadInfoPacket != null -> proto.imageUploadInfoPacket
proto.imageDownloadInfo != null -> proto.imageDownloadInfo

View File

@ -94,6 +94,7 @@ abstract class KnownEventParserAndHandler<TPacket : Packet>(override val id: USh
GroupFileUploadEventFactory,
GroupMemberPermissionChangedEventFactory,
GroupMessageEventParserAndHandler,
FriendMessageEventParserAndHandler
FriendMessageEventParserAndHandler,
FriendAddRequestEventPacket
)
}

View File

@ -0,0 +1,120 @@
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.network.protocol.tim.packet.event
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import kotlinx.io.core.readUInt
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.network.protocol.tim.packet.PacketVersion
import net.mamoe.mirai.network.protocol.tim.packet.action.AddFriendPacket
import net.mamoe.mirai.network.qqAccount
import net.mamoe.mirai.utils.io.readUShortLVString
import net.mamoe.mirai.withSession
import kotlin.jvm.JvmOverloads
/**
* 陌生人请求添加机器人账号为好友
*/
data class ReceiveFriendAddRequestEvent(
val qq: QQ,
/**
* 验证消息
*/
val message: String
) : EventPacket {
/**
* 同意这个请求
*
* @param remark 备注名, 不设置则需为 `null`
*/
@JvmOverloads
suspend fun approve(remark: String? = null): Unit = qq.bot.withSession {
AddFriendPacket.Approve(qqAccount, sessionKey, 0, qq.id, remark).sendAndExpect<AddFriendPacket.Response>()
}
}
@PacketVersion(date = "2019.11.20", timVersion = "2.3.2 (21173)")
object FriendAddRequestEventPacket : KnownEventParserAndHandler<ReceiveFriendAddRequestEvent>(0x02DFu) {
override suspend fun ByteReadPacket.parse(bot: Bot, identity: EventPacketIdentity): ReceiveFriendAddRequestEvent = bot.withSession {
// 00 00 00 08 00 0A 00 04 01 00
// 00 00 00 01
// 76 E4 B8 DD
// 00 00 00 01
// 2D 5C 53 A6
// 76 E4 B8 DD
// 02 00 00
// 00 0B BC 00 0B 5D D5 2E A3 04 7C 00 02 00 0C E6 88 91 E6 98 AF E6 A2 A8 E5 A4 B4 00 00
// 有验证消息
// 00 00 00 08 00 0A 00 04 01 00
// 00 00 00 01
// 76 E4 B8 DD
// 00 00 00 01
// 2D 5C 53 A6
// 76 E4 B8 DD
// 02 00 00
// 09 0B BD 00 02 5D D5 32 50 04 7C 00 02 00 00 00 00
// 无验证消息
// 00 00 00 08 00 0A 00 04 01 00
// 00 00 00 01
// 76 E4 B8 DD
// 00 00 00 01
// 2D 5C 53 A6
// 76 E4 B8 DD
// 02 00 00
// 09 0B BD 00 02 5D D5 33 0C 04 7C 00 02 00 0C E6 88 91 E6 98 AF E6 A2 A8 E5 A4 B4 00 00
// 有验证消息
/*
Mirai 20:35:23 : Packet received: UnknownEventPacket(id=02 10, identity=(761025446->1994701021))
= 00 00 00 08 00 0A 00 04 01 00 00 00 00 00 00 06 00 00 00 4C 08 02 1A 02 08 23 0A 4A 08 DD F1 92 B7 07 10 A6 A7 F1 EA 02 18 02 20 00 28 01 30 09 38 BD 17 40 02 48 8C E6 D4 EE 05 52 0C E6 88 91 E6 98 AF E6 A2 A8 E5 A4 B4 5A 0F E6 9D A5 E8 87 AA E8 AE A8 E8 AE BA E7 BB 84 62 00 6A 06 08 A5 CE 85 8A 06 72 00
Mirai 20:35:23 : Packet received: UnknownEventPacket(id=02 DF, identity=(761025446->1994701021))
= 00 00 00 08 00 0A 00 04 01 00 00 00 00 01 76 E4 B8 DD 00 00 00 01 2D 5C 53 A6 76 E4 B8 DD 02 00 00 09 0B BD 00 02 5D D5 33 0C 04 7C 00 02 00 0C E6 88 91 E6 98 AF E6 A2 A8 E5 A4 B4 00 00
Mirai 20:35:23 : Packet received: UnknownEventPacket(id=00 BB, identity=(761025446->1994701021))
= 00 00 00 08 00 0A 00 04 01 00 00 00 01 0C E6 88 91 E6 98 AF E6 A2 A8 E5 A4 B4 01 0B BD 00 02 00 00 00 5E 00 00 00 00 00 00 00 00 01 04 03 EF 00 06 08 A5 CE 85 8A 06 03 F0 00 02 08 01 03 F2 00 14 00 00 00 82 00 00 00 6D 2F AF 0B ED 20 02 EB 94 00 00 00 00 03 ED 00 28 08 01 12 18 68 69 6D 31 38 38 E7 9A 84 E8 80 81 E5 85 AC E7 9A 84 E6 9B BF E8 BA AB 18 00 22 06 E6 A2 A8 E5 A4 B4 28 01
*/
//Mirai 20:32:15 : Packet received: UnknownEventPacket(id=02 DF, identity=(761025446->1994701021))
// = 00 00 00 08 00 0A 00 04 01 00 00 00 00 01 76 E4 B8 DD 00 00 00 01 2D 5C 53 A6 76 E4 B8 DD 02 00 00 09 0B BD 00 02 5D D5 32 50 04 7C 00 02 00 00 00 00
//Mirai 20:32:15 : Packet received: UnknownEventPacket(id=02 10, identity=(761025446->1994701021))
// = 00 00 00 08 00 0A 00 04 01 00 00 00 00 00 00 06 00 00 00 40 08 02 1A 02 08 23 0A 3E 08 DD F1 92 B7 07 10 A6 A7 F1 EA 02 18 02 20 00 28 01 30 09 38 BD 17 40 02 48 D0 E4 D4 EE 05 52 00 5A 0F E6 9D A5 E8 87 AA E8 AE A8 E8 AE BA E7 BB 84 62 00 6A 06 08 A5 CE 85 8A 06 72 00
//Mirai 20:32:15 : Packet received: UnknownEventPacket(id=00 BB, identity=(761025446->1994701021))
// = 00 00 00 08 00 0A 00 04 01 00 00 00 01 00 01 0B BD 00 02 00 00 00 5E 00 00 00 00 00 00 00 00 01 04 03 EF 00 06 08 A5 CE 85 8A 06 03 F0 00 02 08 01 03 F2 00 14 00 00 00 82 00 00 00 6D 2F AF 0B ED 20 02 EB 94 00 00 00 00 03 ED 00 28 08 01 12 18 68 69 6D 31 38 38 E7 9A 84 E8 80 81 E5 85 AC E7 9A 84 E6 9B BF E8 BA AB 18 00 22 06 E6 A2 A8 E5 A4 B4 28 01
discardExact(10 + 4) // 00 00 00 08 00 0A 00 04 01 00 00 00 00 01
discardExact(4) // bot account uint
discardExact(4) // 00 00 00 01
val qq = readUInt().qq()
discardExact(4) // bot account uint
discardExact(3) // 02 00 00 恒定
discardExact(11) // 不确定. 以下为可能的值
// 00 00 01 00 01 5D D5 3C 57 00 A8 , 1994701021 添加 761025446
// 09 0B BD 00 02 5D D5 33 0C 04 7C 有验证, 761025446 添加 1994701021
// 09 0B BD 00 02 5D D5 32 50 04 7C 无验证, 761025446 添加 1994701021
// 00 0B BC 00 0B 5D D5 2E A3 04 7C 有验证
val message = readUShortLVString()
discardExact(2) // 00 01
return ReceiveFriendAddRequestEvent(qq, message)
}
}
/*
1994701021 761025446 发出好友请求, 761025446 收到 0x02DF 事件, body=
00 00 00 08 00 0A 00 04 01 00
00 00 00 01
2D 5C 53 A6
00 00 00 01
76 E4 B8 DD
2D 5C 53 A6
02 00 00
00 00 01 00 01 5D D5 3C 57 00 A8 00 02 00 00 00 00
*/

View File

@ -72,7 +72,7 @@ enum class ProtoType(val value: Byte, private val typeName: String) {
override fun toString(): String = this.typeName
companion object {
fun valueOf(value: Byte): ProtoType = values().firstOrNull { it.value == value } ?: error("Unknown ProtoId $value")
fun valueOf(value: Byte): ProtoType = values().firstOrNull { it.value == value } ?: error("Unknown ProtoType $value")
}
}
@ -144,7 +144,8 @@ fun ByteReadPacket.readProtoMap(length: Long = this.remaining): ProtoMap {
require(this.remaining > expectingRemaining) { "Expecting to read $length bytes, but read ${expectingRemaining + length - this.remaining}" }
val id = ProtoFieldId(readUVarInt())
map[id] = when (id.type) {
fun readValue(): Any = when (id.type) {
ProtoType.VAR_INT -> UVarInt(readUVarInt())
ProtoType.BIT_32 -> readUInt()
ProtoType.BIT_64 -> readULong()
@ -153,6 +154,19 @@ fun ByteReadPacket.readProtoMap(length: Long = this.remaining): ProtoMap {
ProtoType.START_GROUP -> Unit
ProtoType.END_GROUP -> Unit
}
if (map.containsKey(id)) {
if (map[id] is MutableList<*>) {
@Suppress("UNCHECKED_CAST")
(map[id] as MutableList<Any>) += readValue()
} else {
map[id] = mutableListOf(map[id]!!)
@Suppress("UNCHECKED_CAST")
(map[id] as MutableList<Any>) += readValue()
}
} else {
map[id] = readValue()
}
}
return map
}

View File

@ -12,6 +12,13 @@ internal object DebugLogger : MiraiLogger by DefaultLogger("Packet Debug")
internal fun debugPrintln(any: Any?) = DebugLogger.debug(any)
@Deprecated("Low efficiency, only for debug purpose", ReplaceWith("this"))
internal fun String.debugPrint(name: String): String {
DebugLogger.debug("$name=$this")
return this
}
@Deprecated("Low efficiency, only for debug purpose", ReplaceWith("this"))
internal fun ByteArray.debugPrint(name: String): ByteArray {
DebugLogger.debug(name + "=" + this.toUHexString())
return this
@ -67,7 +74,6 @@ internal fun BytePacketBuilder.debugColorizedPrintThis(name: String = "", compar
@Deprecated("Low efficiency, only for debug purpose", ReplaceWith(" "))
internal fun BytePacketBuilder.debugPrintThis(name: String = "") {
val data = this.build().readBytes()
data.debugPrint(name)
this.writeFully(data)
}

View File

@ -118,8 +118,8 @@ object PacketDebugger {
* 7. 运行完 `mov eax,dword ptr ss:[ebp+10]`
* 8. 查看内存, `eax` `eax+10` 16 字节就是 `sessionKey`
*/
val sessionKey: SessionKey = SessionKey("FF 75 0E 37 92 1C F3 A2 44 77 8A 61 44 29 EA D8".hexToBytes())
const val qq: UInt = 1040400290u
val sessionKey: SessionKey = SessionKey("15 95 8D 22 F7 3B C6 6E FE 91 1B 1B 8F A2 9E 1C".hexToBytes())
const val qq: UInt = 761025446u
val IgnoredPacketIdList: List<PacketId> = listOf(
KnownPacketId.FRIEND_ONLINE_STATUS_CHANGE,

View File

@ -9,10 +9,12 @@ import kotlinx.serialization.protobuf.ProtoBuf
import kotlinx.serialization.protobuf.ProtoNumberType
import kotlinx.serialization.protobuf.ProtoType
import kotlinx.serialization.serializer
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.ProtoFieldId
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
@ -58,17 +60,15 @@ suspend fun main() {
}
suspend fun deserializeTest() {
println(Http.getURL("http://gchat.qpic.cn/gchatpic_new/1994701021/1994701021-2868483628-39F76532E1AB5CA786D7A51389225385/0?vuin=1994701021&term=255&srvver=26933").remaining)
//println(Http.getURL("http://gchat.qpic.cn/gchatpic_new/1994701021/1994701021-2868483628-39F76532E1AB5CA786D7A51389225385/0?vuin=1994701021&term=255&srvver=26933").remaining)
val bytes =
"""
10 02 22 4E 08 A0 89 F7 B6 03 10 A2 FF 8C F0 03 18 BB 92 94 BF 08 22 10 63 B1 86 6F 41 3E D9 78 CB CF 53 3E 92 28 5C 58 28 04 30 02 38 20 40 FF 01 48 00 50 01 5A 05 32 36 39 33 33 60 00 68 00 70 00 78 00 80 01 97 04 88 01 ED 03 90 01 04 A0 01 01
""".trimIndent().replace("\n", " ").replace("[", "").replace("]", "")
08 01 10 00 1A 89 02 10 01 18 03 3A 4D 08 A6 A7 F1 EA 02 10 DD F1 92 B7 07 18 01 20 D3 81 D5 EE 05 2A 00 32 11 E6 9D A5 E8 87 AA 51 51 E5 8F B7 E6 9F A5 E6 89 BE 38 01 40 01 48 00 50 00 58 00 60 01 6A 00 70 00 78 00 80 01 03 A0 01 00 A8 01 00 B0 01 00 C0 01 01 E8 01 00 3A 4A 08 A6 A7 F1 EA 02 10 DD F1 92 B7 07 18 03 20 DC 80 D5 EE 05 2A 00 32 11 E6 9D A5 E8 87 AA 51 51 E5 8F B7 E6 9F A5 E6 89 BE 38 01 40 01 48 00 50 00 58 00 60 01 6A 00 70 00 78 00 80 01 00 A0 01 00 A8 01 00 B0 01 00 C0 01 00 3A 4A 08 A6 A7 F1 EA 02 10 DD F1 92 B7 07 18 03 20 D7 F8 D4 EE 05 2A 00 32 11 E6 9D A5 E8 87 AA 51 51 E5 8F B7 E6 9F A5 E6 89 BE 38 01 40 01 48 00 50 00 58 00 60 01 6A 00 70 00 78 00 80 01 00 A0 01 00 A8 01 00 B0 01 00 C0 01 00 40 D3 81 D5 EE 05 48 01 50 01 58 01 60 DD F1 92 B7 07 72 08 0A 06 08 DD F1 92 B7 07 78 00
""".trimIndent().replace("\n", " ").replace("[", "").replace("]", "")
.hexToBytes()
/*

View File

@ -17,6 +17,7 @@ import net.mamoe.mirai.message.getValue
import net.mamoe.mirai.message.sendAsImageTo
import net.mamoe.mirai.network.protocol.tim.packet.event.FriendMessage
import net.mamoe.mirai.network.protocol.tim.packet.event.GroupMessage
import net.mamoe.mirai.network.protocol.tim.packet.event.ReceiveFriendAddRequestEvent
import net.mamoe.mirai.network.protocol.tim.packet.login.requireSuccess
import java.io.File
import java.util.*
@ -54,6 +55,10 @@ suspend fun main() {
//bot.logger.verbose("收到了一个事件: ${it::class.simpleName}")
}
subscribeAlways<ReceiveFriendAddRequestEvent> {
it.approve()
}
bot.subscribeMessages {
"你好" reply "你好!"