Commit 12944417 authored by Him188's avatar Him188

GroupImageDownload supports

parent 44a6ba16
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
package net.mamoe.mirai.network.protocol.tim.packet.action package net.mamoe.mirai.network.protocol.tim.packet.action
import io.ktor.client.request.get
import kotlinx.io.charsets.Charsets import kotlinx.io.charsets.Charsets
import kotlinx.io.core.* import kotlinx.io.core.*
import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.message.ImageId import net.mamoe.mirai.message.ImageId
import net.mamoe.mirai.message.ImageId0x06
import net.mamoe.mirai.message.requireLength import net.mamoe.mirai.message.requireLength
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.protocol.tim.TIMProtocol import net.mamoe.mirai.network.protocol.tim.TIMProtocol
...@@ -59,11 +59,8 @@ interface FriendImageResponse : EventPacket ...@@ -59,11 +59,8 @@ interface FriendImageResponse : EventPacket
* 图片数据地址. * 图片数据地址.
*/ */
// TODO: 2019/11/15 应该为 inline class, 但 kotlin 有 bug // TODO: 2019/11/15 应该为 inline class, 但 kotlin 有 bug
data class FriendImageLink(inline val value: String) : FriendImageResponse { data class FriendImageLink(override inline val original: String) : FriendImageResponse, ImageLink {
suspend fun downloadAsByteArray(): ByteArray = download().readBytes() override fun toString(): String = "FriendImageLink($original)"
suspend fun download(): ByteReadPacket = Http.get(value)
override fun toString(): String = "FriendImageLink($value)"
} }
/** /**
...@@ -199,7 +196,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() { ...@@ -199,7 +196,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() {
writeUByte(0x1Au) writeUByte(0x1Au)
writeUByte(0x47u) writeUByte(0x47u)
writeTUVarint(0x08u, bot) writeTUVarint(0x08u, bot)
writeTUVarint(0x10u, bot) writeTUVarint(0x10u, bot) // 这里实际上应该是这张图片来自哪个 QQ 号. 但传 bot 也没事.
writeTLV(0x1Au, imageId.value.toByteArray(Charsets.ISO_8859_1)) writeTLV(0x1Au, imageId.value.toByteArray(Charsets.ISO_8859_1))
writeHex("20 02 30 04 38 20 40 FF 01 50 00 6A 05 32 36 39 33 33 78 01") writeHex("20 02 30 04 38 20 40 FF 01 50 00 6A 05 32 36 39 33 33 78 01")
} }
...@@ -276,7 +273,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() { ...@@ -276,7 +273,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() {
while (readUByte().toUInt() != 0x4Au) readUVarLong() while (readUByte().toUInt() != 0x4Au) readUVarLong()
val uKey = readBytes(readUVarInt().toInt())//128 val uKey = readBytes(readUVarInt().toInt())//128
while (readUByte().toUInt() != 0x52u) readUVarLong() while (readUByte().toUInt() != 0x52u) readUVarLong()
val imageId = ImageId(readString(readUVarInt().toInt()))//37 val imageId = ImageId0x06(readString(readUVarInt().toInt()))//37
return FriendImageUKey(imageId, uKey) return FriendImageUKey(imageId, uKey)
} catch (e: EOFException) { } catch (e: EOFException) {
val toDiscard = readUByte().toInt() - 37 val toDiscard = readUByte().toInt() - 37
...@@ -285,7 +282,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() { ...@@ -285,7 +282,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() {
FriendImageOverFileSizeMax FriendImageOverFileSizeMax
} else { } else {
discardExact(toDiscard) discardExact(toDiscard)
val imageId = ImageId(readString(37)) val imageId = ImageId0x06(readString(37))
FriendImageAlreadyExists(imageId) FriendImageAlreadyExists(imageId)
} }
} }
...@@ -302,6 +299,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() { ...@@ -302,6 +299,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() {
// 3A 00 80 01 00 // 3A 00 80 01 00
//00 00 00 08 00 00 //00 00 00 08 00 00
// [02 29] // [02 29]
// 12 [06] 98 01 02 A0 01 00 // 12 [06] 98 01 02 A0 01 00
...@@ -315,7 +313,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() { ...@@ -315,7 +313,7 @@ object FriendImagePacket : SessionPacketFactory<FriendImageResponse>() {
discardExact(1) discardExact(1)
discardExact(2)// [A4 04] 后文长度 discardExact(2)// [A4 04] 后文长度
check(readUByte().toUInt() == 0x0Au) { "Illegal identity. Required 0x0Au" } check(readUByte().toUInt() == 0x0Au) { "Illegal identity. Required 0x0Au" }
/* val imageId = */ImageId(readString(readUByte().toInt())) /* val imageId = */ImageId0x06(readString(readUByte().toInt()))
check(readUByte().toUInt() == 0x18u) { "Illegal identity. Required 0x18u" } check(readUByte().toUInt() == 0x18u) { "Illegal identity. Required 0x18u" }
check(readUShort().toUInt() == 0x0032u) { "Illegal identity. Required 0x0032u" } check(readUShort().toUInt() == 0x0032u) { "Illegal identity. Required 0x0032u" }
......
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS", "unused", "NO_REFLECTION_IN_CLASS_PATH")
package net.mamoe.mirai.network.protocol.tim.packet.action
import io.ktor.client.request.get
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readBytes
import net.mamoe.mirai.utils.Http
/**
* 图片文件过大
*/
class OverFileSizeMaxException : IllegalStateException()
interface ImageLink {
/**
* 原图
*/
val original: String
suspend fun downloadAsByteArray(): ByteArray = download().readBytes()
suspend fun download(): ByteReadPacket = Http.get(original)
}
/*
/**
* 似乎没有必要. 服务器的返回永远都是 01 00 00 00 02 00 00
*/
@Deprecated("Useless packet")
@AnnotatedId(KnownPacketId.SUBMIT_IMAGE_FILE_NAME)
@PacketVersion(date = "2019.10.26", timVersion = "2.3.2 (21173)")
object SubmitImageFilenamePacket : PacketFactory {
operator fun invoke(
bot: UInt,
target: UInt,
filename: String,
sessionKey: SessionKey
): OutgoingPacket = buildOutgoingPacket {
writeQQ(bot)
writeFully(TIMProtocol.fixVer2)//?
//writeHex("04 00 00 00 01 2E 01 00 00 69 35")
encryptAndWrite(sessionKey) {
writeByte(0x01)
writeQQ(bot)
writeQQ(target)
writeZero(2)
writeUByte(0x02u)
writeRandom(1)
writeHex("00 0A 00 01 00 01")
val name = "UserDataImage:$filename"
writeShort(name.length.toShort())
writeStringUtf8(name)
writeHex("00 00")
writeRandom(2)//这个也与是哪个好友有关?
writeHex("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 2E 01")//35 02? 最后这个值是与是哪个好友有关
//this.debugPrintThis("SubmitImageFilenamePacket")
}
//解密body=01 3E 03 3F A2 7C BC D3 C1 00 00 27 1A 00 0A 00 01 00 01 00 30 55 73 65 72 44 61 74 61 43 75 73 74 6F 6D 46 61 63 65 3A 31 5C 28 5A 53 41 58 40 57 4B 52 4A 5A 31 7E 33 59 4F 53 53 4C 4D 32 4B 49 2E 6A 70 67 00 00 06 E2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 2F 02
//解密body=01 3E 03 3F A2 7C BC D3 C1 00 00 27 1B 00 0A 00 01 00 01 00 30 55 73 65 72 44 61 74 61 43 75 73 74 6F 6D 46 61 63 65 3A 31 5C 28 5A 53 41 58 40 57 4B 52 4A 5A 31 7E 33 59 4F 53 53 4C 4D 32 4B 49 2E 6A 70 67 00 00 06 E2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 2F 02
//解密body=01 3E 03 3F A2 7C BC D3 C1 00 00 27 1C 00 0A 00 01 00 01 00 30 55 73 65 72 44 61 74 61 43 75 73 74 6F 6D 46 61 63 65 3A 31 5C 29 37 42 53 4B 48 32 44 35 54 51 28 5A 35 7D 35 24 56 5D 32 35 49 4E 2E 6A 70 67 00 00 03 73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 2F 02
}
@PacketVersion(date = "2019.10.19", timVersion = "2.3.2 (21173)")
class Response {
override fun decode() = with(input) {
require(readBytes().contentEquals(expecting))
}
companion object {
private val expecting = byteArrayOf(0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00)
}
}
}*/
// regiion GroupImageResponse
...@@ -5,24 +5,25 @@ package net.mamoe.mirai.network.protocol.tim.packet.event ...@@ -5,24 +5,25 @@ package net.mamoe.mirai.network.protocol.tim.packet.event
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import kotlinx.io.core.readUInt import kotlinx.io.core.readUInt
import net.mamoe.mirai.* import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.event.BroadcastControllable import net.mamoe.mirai.event.BroadcastControllable
import net.mamoe.mirai.event.events.BotEvent import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.getGroup
import net.mamoe.mirai.getQQ
import net.mamoe.mirai.message.* import net.mamoe.mirai.message.*
import net.mamoe.mirai.message.internal.readMessageChain import net.mamoe.mirai.message.internal.readMessageChain
import net.mamoe.mirai.network.protocol.tim.packet.PacketVersion import net.mamoe.mirai.network.protocol.tim.packet.PacketVersion
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendImageLink import net.mamoe.mirai.network.protocol.tim.packet.action.ImageLink
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendImagePacket
import net.mamoe.mirai.network.sessionKey
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.printTLVMap import net.mamoe.mirai.utils.io.printTLVMap
import net.mamoe.mirai.utils.io.read import net.mamoe.mirai.utils.io.read
import net.mamoe.mirai.utils.io.readTLVMap import net.mamoe.mirai.utils.io.readTLVMap
import net.mamoe.mirai.utils.io.readUShortLVByteArray import net.mamoe.mirai.utils.io.readUShortLVByteArray
import net.mamoe.mirai.withSession
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
/** /**
...@@ -87,8 +88,8 @@ abstract class MessagePacketBase<TSubject : Contact> : EventPacket, BotEvent() { ...@@ -87,8 +88,8 @@ abstract class MessagePacketBase<TSubject : Contact> : EventPacket, BotEvent() {
// endregion // endregion
// region Image download // region Image download
suspend inline fun Image.getLink(): ImageLink = bot.withSession { getLink() }
suspend fun Image.getLink(): FriendImageLink = bot.withSession { FriendImagePacket.RequestImageLink(bot.qqAccount, bot.sessionKey, id).sendAndExpect() }
suspend inline fun Image.downloadAsByteArray(): ByteArray = getLink().downloadAsByteArray() suspend inline fun Image.downloadAsByteArray(): ByteArray = getLink().downloadAsByteArray()
suspend inline fun Image.download(): ByteReadPacket = getLink().download() suspend inline fun Image.download(): ByteReadPacket = getLink().download()
// endregion // endregion
...@@ -106,6 +107,7 @@ data class GroupMessage( ...@@ -106,6 +107,7 @@ data class GroupMessage(
override val sender: QQ, override val sender: QQ,
override val message: MessageChain = NullMessageChain override val message: MessageChain = NullMessageChain
) : MessagePacket<Group>() { ) : MessagePacket<Group>() {
override val subject: Group get() = group override val subject: Group get() = group
} }
......
...@@ -7,10 +7,7 @@ import kotlinx.io.core.Input ...@@ -7,10 +7,7 @@ import kotlinx.io.core.Input
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.message.Image import net.mamoe.mirai.message.*
import net.mamoe.mirai.message.ImageId
import net.mamoe.mirai.message.image
import net.mamoe.mirai.message.sendTo
import net.mamoe.mirai.network.protocol.tim.packet.action.uploadImage import net.mamoe.mirai.network.protocol.tim.packet.action.uploadImage
import net.mamoe.mirai.utils.io.toUHexString import net.mamoe.mirai.utils.io.toUHexString
...@@ -52,7 +49,8 @@ class ExternalImage( ...@@ -52,7 +49,8 @@ class ExternalImage(
/** /**
* 用于发送消息的 [ImageId] * 用于发送消息的 [ImageId]
*/ */
val groupImageId: ImageId by lazy { ImageId("{${md5[0..3]}-${md5[4..5]}-${md5[6..7]}-${md5[8..9]}-${md5[10..15]}}.$format") } @Suppress("EXPERIMENTAL_UNSIGNED_LITERALS")
val groupImageId: ImageId by lazy { ImageId0x03("{${md5[0..3]}-${md5[4..5]}-${md5[6..7]}-${md5[8..9]}-${md5[10..15]}}.$format", 0u, height, width) }
override fun toString(): String = "[ExternalImage(${width}x$height $format)]" override fun toString(): String = "[ExternalImage(${width}x$height $format)]"
} }
......
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