mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-15 16:10:12 +08:00
Image uploading
This commit is contained in:
parent
d06197d346
commit
14722eb838
@ -30,7 +30,7 @@ abstract class ClientPacket : Packet(), Closeable {
|
||||
/**
|
||||
* 务必 [ByteReadPacket.close] 或 [close] 或使用 [Closeable.use]
|
||||
*/
|
||||
internal var packet: ByteReadPacket = UninitializedByteReadPacket
|
||||
var packet: ByteReadPacket = UninitializedByteReadPacket
|
||||
get() {
|
||||
if (field === UninitializedByteReadPacket) build()
|
||||
return field
|
||||
|
@ -4,11 +4,11 @@ package net.mamoe.mirai.network.protocol.tim.packet
|
||||
|
||||
import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
|
||||
import net.mamoe.mirai.network.session
|
||||
import net.mamoe.mirai.qqAccount
|
||||
import net.mamoe.mirai.utils.*
|
||||
|
||||
|
||||
suspend fun Group.uploadImage(
|
||||
image: PlatformImage
|
||||
) = with(bot.network.session) {
|
||||
@ -110,54 +110,79 @@ class GroupImageIdRequestPacket(
|
||||
// 78 03
|
||||
// 80 01 00
|
||||
|
||||
|
||||
/*
|
||||
writeQQ(bot)
|
||||
writeHex(TIMProtocol.version0x04)
|
||||
|
||||
encryptAndWrite(sessionKey) {
|
||||
writeHex("00 00 00 07 00 00 00")
|
||||
|
||||
writeUVarintLVPacket(lengthOffset = { it - 6 }) {
|
||||
writeUVarintLVPacket {
|
||||
writeByte(0x08)
|
||||
writeHex("01 12 03 98 01 01 10 01 1A")
|
||||
|
||||
writeUVarintLVPacket(lengthOffset = { it + 1 }) {
|
||||
writeUVarInt(groupId)
|
||||
writeUVarInt(bot)
|
||||
|
||||
writeUVarintLVPacket(lengthOffset = { it + 7 }) {
|
||||
writeTUVarint(0x08u, groupId)
|
||||
writeTUVarint(0x10u, bot)
|
||||
writeTV(0x1800u)
|
||||
writeTLV(0x22u, image.md5)
|
||||
writeTUVarint(0x28u, image.fileSize.toUInt())
|
||||
writeUVarintLVPacket(tag = 0x32u) {
|
||||
writeTV(0x31_00u)
|
||||
writeTV(0x35_00u)
|
||||
writeTV(0x4C_00u)
|
||||
writeTV(0x5B_00u)
|
||||
writeTV(0x40_00u)
|
||||
writeTV(0x33_00u)
|
||||
writeTV(0x48_00u)
|
||||
writeTV(0x5F_00u)
|
||||
writeTV(0x58_00u)
|
||||
writeTV(0x46_00u)
|
||||
writeTV(0x51_00u)
|
||||
writeTV(0x45_00u)
|
||||
writeTV(0x51_00u)
|
||||
writeTV(0x40_00u)
|
||||
writeTV(0x24_00u)
|
||||
writeTV(0x40_00u)
|
||||
writeTV(0x5B_00u)
|
||||
writeTV(0x4D_00u)
|
||||
writeTV(0x5B_00u)
|
||||
writeTV(0x39_00u)
|
||||
writeTV(0x39_00u)
|
||||
writeTV(0x40_00u)
|
||||
writeTV(0x57_00u)
|
||||
writeTV(0x5D_00u)
|
||||
writeTV(0x4F_00u)
|
||||
}
|
||||
writeTV(0x38_01u)
|
||||
writeTV(0x48_01u)
|
||||
writeTUVarint(0x50u, image.imageWidth.toUInt())
|
||||
writeTUVarint(0x58u, image.imageHeight.toUInt())
|
||||
writeTV(0x60_02u)
|
||||
writeTLV(0x6Au, value0x6A)
|
||||
writeTV(0x70_00u)
|
||||
writeTV(0x78_03u)
|
||||
writeTV(0x80_01u)
|
||||
writeUByte(0u)
|
||||
writeTByteArray(0x6Au, value0x6A)
|
||||
}
|
||||
}
|
||||
writeTV(0x70_00u)
|
||||
writeTV(0x78_03u)
|
||||
writeTV(0x80_01u)
|
||||
writeUByte(0u)
|
||||
|
||||
// this.debugColorizedPrintThis(compareTo = "00 00 00 07 00 00 00 5D 08 01 12 03 98 01 01 10 01 1A 59 08 FB D2 D8 94 02 10 A2 FF 8C F0 03 18 00 22 10 1D D2 2B 9B BC F2 10 83 DC 99 D2 2E 20 39 CC 0E 28 8A 03 32 1A 5B 00 40 00 33 00 48 00 5F 00 58 00 46 00 51 00 45 00 51 00 40 00 24 00 4F 00 38 01 48 01 50 EF 01 58 C2 01 60 02 6A 05 32 36 39 33 33 70 00 78 03 80 01 00")
|
||||
}*/
|
||||
|
||||
writeQQ(bot)
|
||||
writeHex("04 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 00 00 00")
|
||||
|
||||
encryptAndWrite(sessionKey) {
|
||||
writeHex("00 00 00 07 00 00 00 5E 08 01 12 03 98 01 01 10 01 1A")
|
||||
writeHex("5A 08")
|
||||
writeUVarInt(groupId)
|
||||
writeUByte(0x10u)
|
||||
writeUVarInt(bot)
|
||||
writeHex("18 00 22 10")
|
||||
writeFully(image.md5)
|
||||
writeUByte(0x28u)
|
||||
writeUVarInt(image.fileSize.toUInt())
|
||||
writeHex("32 1A 37 00 4D 00 32 00 25 00 4C 00 31 00 56 00 32 00 7B 00 39 00 30 00 29 00 52 00")
|
||||
writeHex("38 01 48 01 50")
|
||||
writeUVarInt(image.width.toUInt())
|
||||
writeUByte(0x58u)
|
||||
writeUVarInt(image.height.toUInt())
|
||||
writeHex("60 04 6A 05 32 36 36 35 36 70 00 78 03 80 01 00")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val value0x6A: UByteArray = ubyteArrayOf(32u, 36u, 39u, 33u, 33u)
|
||||
private val value0x6A: UByteArray = ubyteArrayOf(0x05u, 0x32u, 0x36u, 0x39u, 0x33u, 0x33u)
|
||||
}
|
||||
|
||||
@PacketId(0x0388u)
|
||||
@ -189,7 +214,7 @@ class GroupImageIdRequestPacket(
|
||||
}
|
||||
|
||||
fun main() {
|
||||
("12 03 98 01 01").hexToBytes().read {
|
||||
("8E 4B").hexToBytes().read {
|
||||
println(readUnsignedVarInt())
|
||||
}
|
||||
|
||||
|
@ -119,8 +119,7 @@ abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: Event
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略的事件.
|
||||
* 如 00 79: 总是与 01 12 一起发生, 但 00 79 却没多大意义
|
||||
* 忽略的事件
|
||||
*/
|
||||
@Suppress("unused")
|
||||
class IgnoredServerEventPacket(val eventId: ByteArray, private val showData: Boolean = false, input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
|
@ -3,7 +3,7 @@ package net.mamoe.mirai.utils
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.message.ImageId
|
||||
|
||||
data class PlatformImage(
|
||||
class PlatformImage(
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
val md5: ByteArray,
|
||||
@ -14,30 +14,7 @@ data class PlatformImage(
|
||||
|
||||
val id: ImageId by lazy { ImageId("{${md5[0..4]}-${md5[0..2]}-${md5[0..2]}-${md5[0..2]}-${md5[0..6]}}.$format") }
|
||||
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is PlatformImage) return false
|
||||
|
||||
if (width != other.width) return false
|
||||
if (height != other.height) return false
|
||||
if (!md5.contentEquals(other.md5)) return false
|
||||
if (format != other.format) return false
|
||||
if (fileData != other.fileData) return false
|
||||
if (fileSize != other.fileSize) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = width
|
||||
result = 31 * result + height
|
||||
result = 31 * result + md5.contentHashCode()
|
||||
result = 31 * result + format.hashCode()
|
||||
result = 31 * result + fileData.hashCode()
|
||||
result = 31 * result + fileSize.hashCode()
|
||||
return result
|
||||
}
|
||||
override fun toString(): String = "[PlatformImage(${width}x${height} $format)]"
|
||||
}
|
||||
|
||||
private operator fun ByteArray.get(range: IntRange): String = buildString {
|
||||
|
@ -45,6 +45,13 @@ internal fun BytePacketBuilder.debugColorizedPrintThis(name: String = "") {
|
||||
this.writeFully(data)
|
||||
}
|
||||
|
||||
@Deprecated("Low efficiency, only for debug purpose", ReplaceWith(" "))
|
||||
internal fun BytePacketBuilder.debugColorizedPrintThis(name: String = "", compareTo: String? = null) {
|
||||
val data = this.build().readBytes()
|
||||
data.printColorizedHex(name, compareTo = compareTo)
|
||||
this.writeFully(data)
|
||||
}
|
||||
|
||||
@Deprecated("Low efficiency, only for debug purpose", ReplaceWith(" "))
|
||||
internal fun BytePacketBuilder.debugPrintThis(name: String = "") {
|
||||
val data = this.build().readBytes()
|
||||
@ -57,14 +64,18 @@ internal fun String.printStringFromHex() {
|
||||
}
|
||||
|
||||
|
||||
internal fun ByteArray.printColorizedHex(name: String = "", ignoreUntilFirstConst: Boolean = false) {
|
||||
internal fun ByteArray.printColorizedHex(name: String = "", ignoreUntilFirstConst: Boolean = false, compareTo: String? = null) {
|
||||
println("Hex比较 `$name`")
|
||||
println(toUHexString().colorize(ignoreUntilFirstConst))
|
||||
if (compareTo != null) {
|
||||
println(printCompareHex(toUHexString(), compareTo))
|
||||
} else {
|
||||
println(toUHexString().printColorize(ignoreUntilFirstConst))
|
||||
}
|
||||
println()
|
||||
}
|
||||
|
||||
expect fun compareHex(hex1s: String, hex2s: String): String
|
||||
expect fun String.colorize(ignoreUntilFirstConst: Boolean = false): String
|
||||
expect fun printCompareHex(hex1s: String, hex2s: String): String
|
||||
expect fun String.printColorize(ignoreUntilFirstConst: Boolean = false): String
|
||||
|
||||
|
||||
fun main() {
|
||||
|
@ -92,6 +92,11 @@ fun BytePacketBuilder.writeTByteArray(tag: UByte, value: ByteArray) {
|
||||
this.writeFully(value)
|
||||
}
|
||||
|
||||
fun BytePacketBuilder.writeTByteArray(tag: UByte, value: UByteArray) {
|
||||
this.writeUByte(tag)
|
||||
this.writeFully(value)
|
||||
}
|
||||
|
||||
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(keyHex: String, encoder: BytePacketBuilder.() -> Unit) = encryptAndWrite(keyHex.hexToBytes(), encoder)
|
||||
|
@ -74,8 +74,8 @@ internal object HexCache {
|
||||
}
|
||||
|
||||
internal fun hexToUBytes(hex: String): UByteArray =
|
||||
hex.split(" ").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
.map { value -> value.trim { it <= ' ' } }
|
||||
hex.split(" ")
|
||||
.filterNot { it.isEmpty() }
|
||||
.map { s -> s.toUByte(16) }
|
||||
.toUByteArray()
|
||||
}
|
@ -286,5 +286,5 @@ internal object HexComparator {
|
||||
|
||||
}
|
||||
|
||||
actual fun String.colorize(ignoreUntilFirstConst: Boolean): String = with(HexComparator) { colorize(ignoreUntilFirstConst) }
|
||||
actual fun compareHex(hex1s: String, hex2s: String): String = with(HexComparator) { compare(hex1s, hex2s) }
|
||||
actual fun String.printColorize(ignoreUntilFirstConst: Boolean): String = with(HexComparator) { colorize(ignoreUntilFirstConst) }
|
||||
actual fun printCompareHex(hex1s: String, hex2s: String): String = with(HexComparator) { compare(hex1s, hex2s) }
|
@ -8,7 +8,7 @@ import java.io.OutputStream
|
||||
import java.security.MessageDigest
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
fun BufferedImage.toPlatformImage(formatName: String = "PNG"): PlatformImage {
|
||||
fun BufferedImage.toPlatformImage(formatName: String = "png"): PlatformImage {
|
||||
val digest = MessageDigest.getInstance("md5")
|
||||
digest.reset()
|
||||
|
||||
|
23
mirai-core/src/jvmTest/kotlin/TestGroupImage.kt
Normal file
23
mirai-core/src/jvmTest/kotlin/TestGroupImage.kt
Normal file
@ -0,0 +1,23 @@
|
||||
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS")
|
||||
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.GroupImageIdRequestPacket
|
||||
import net.mamoe.mirai.utils.hexToBytes
|
||||
import net.mamoe.mirai.utils.readRemainingBytes
|
||||
import net.mamoe.mirai.utils.toPlatformImage
|
||||
import net.mamoe.mirai.utils.toUHexString
|
||||
import java.io.File
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
val sessionKey: ByteArray = "F1 ED F2 BC 55 17 7B FE CC CC F3 08 D1 8D A7 0E".hexToBytes()
|
||||
|
||||
fun main() = println({
|
||||
val image = ImageIO.read(File("C:\\Users\\Him18\\Desktop\\test2.png").readBytes().inputStream()).toPlatformImage("png")
|
||||
|
||||
// File("C:\\Users\\Him18\\Desktop\\test2.jpg").writeBytes(image.fileData.readBytes())
|
||||
GroupImageIdRequestPacket(
|
||||
1994701021u,
|
||||
580266363u,
|
||||
image,
|
||||
sessionKey
|
||||
).packet.readRemainingBytes().toUHexString()
|
||||
}())
|
@ -1,11 +1,11 @@
|
||||
@file:Suppress("ObjectPropertyName", "unused", "NonAsciiCharacters", "MayBeConstant")
|
||||
|
||||
import net.mamoe.mirai.utils.compareHex
|
||||
import net.mamoe.mirai.utils.printCompareHex
|
||||
import java.util.*
|
||||
|
||||
|
||||
fun main() {
|
||||
// println(HexComparator.colorize("00 00 00 25 00 08 00 02 00 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 01 38 03 3E 03 3F A2 76 E4 B8 DD E7 86 74 F2 64 55 AD 9A EB 2F B9 DF F1 7F 8C 28 00 0B 78 14 5D A2 F5 CB 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D A2 F5 CA 9D 26 CB 5E 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E4 BD A0 E5 A5 BD 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00"))
|
||||
// println(HexComparator.printColorize("00 00 00 25 00 08 00 02 00 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 01 38 03 3E 03 3F A2 76 E4 B8 DD E7 86 74 F2 64 55 AD 9A EB 2F B9 DF F1 7F 8C 28 00 0B 78 14 5D A2 F5 CB 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D A2 F5 CA 9D 26 CB 5E 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E4 BD A0 E5 A5 BD 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00"))
|
||||
val scanner = Scanner(System.`in`)
|
||||
while (true) {
|
||||
println("Hex1: ")
|
||||
@ -13,7 +13,7 @@ fun main() {
|
||||
println("Hex2: ")
|
||||
val hex2 = scanner.nextLine()
|
||||
println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
|
||||
println(compareHex(hex1, hex2))
|
||||
println(printCompareHex(hex1, hex2))
|
||||
println()
|
||||
}
|
||||
/*
|
||||
|
@ -81,14 +81,14 @@ suspend fun main() {
|
||||
|
||||
"上传好友图片" in it.message -> withTimeoutOrNull(3000) {
|
||||
val id = QQ(bot, 1040400290u)
|
||||
.uploadImage(withContext(Dispatchers.IO) { ImageIO.read(File("C:\\Users\\Him18\\Desktop\\lemon.png").readBytes().inputStream()) }.toPlatformImage("PNG"))
|
||||
.uploadImage(withContext(Dispatchers.IO) { ImageIO.read(File("C:\\Users\\Him18\\Desktop\\lemon.png").readBytes().inputStream()) }.toPlatformImage("png"))
|
||||
it.reply(id.value)
|
||||
delay(1000)
|
||||
it.reply(Image(id))
|
||||
}
|
||||
|
||||
"上传群图片" in it.message -> withTimeoutOrNull(3000) {
|
||||
val image = withContext(Dispatchers.IO) { ImageIO.read(File("C:\\Users\\Him18\\Desktop\\lemon.png").readBytes().inputStream()) }.toPlatformImage("PNG")
|
||||
val image = withContext(Dispatchers.IO) { ImageIO.read(File("C:\\Users\\Him18\\Desktop\\lemon.png").readBytes().inputStream()) }.toPlatformImage("png")
|
||||
Group(bot, 580266363u).uploadImage(image)
|
||||
it.reply(image.id.value)
|
||||
delay(1000)
|
||||
|
Loading…
Reference in New Issue
Block a user