Commit a2f35f5d authored by Him188's avatar Him188

ExternalImage

parent 0d7cc17c
...@@ -7,7 +7,9 @@ import net.mamoe.mirai.message.Message ...@@ -7,7 +7,9 @@ import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.MessageChain import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.message.PlainText import net.mamoe.mirai.message.PlainText
import net.mamoe.mirai.message.toChain import net.mamoe.mirai.message.toChain
import net.mamoe.mirai.network.BotSession
import net.mamoe.mirai.network.protocol.tim.handler.EventPacketHandler import net.mamoe.mirai.network.protocol.tim.handler.EventPacketHandler
import net.mamoe.mirai.withSession
class ContactList<C : Contact> : MutableMap<UInt, C> by mutableMapOf() class ContactList<C : Contact> : MutableMap<UInt, C> by mutableMapOf()
...@@ -79,6 +81,8 @@ class Group internal constructor(bot: Bot, id: UInt) : Contact(bot, id) { ...@@ -79,6 +81,8 @@ class Group internal constructor(bot: Bot, id: UInt) : Contact(bot, id) {
companion object companion object
} }
inline fun <R> Group.withSession(block: BotSession.() -> R): R = bot.withSession(block)
/** /**
* QQ 账号. * QQ 账号.
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot]. * 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
......
...@@ -6,19 +6,17 @@ import kotlinx.io.core.IoBuffer ...@@ -6,19 +6,17 @@ import kotlinx.io.core.IoBuffer
import kotlinx.io.core.buildPacket import kotlinx.io.core.buildPacket
import kotlinx.io.streams.asInput import kotlinx.io.streams.asInput
import java.io.File import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.security.MessageDigest import java.security.MessageDigest
import javax.imageio.ImageIO import javax.imageio.ImageIO
import java.awt.image.BufferedImage as JavaBufferedImage import java.awt.image.BufferedImage as JavaBufferedImage
fun JavaBufferedImage.toMiraiImage(formatName: String = "gif"): ExternalImage { fun JavaBufferedImage.toExternalImage(formatName: String = "gif"): ExternalImage {
val digest = MessageDigest.getInstance("md5") val digest = MessageDigest.getInstance("md5")
digest.reset() digest.reset()
val buffer = buildPacket { val buffer = buildPacket {
ImageIO.write(this@toMiraiImage, formatName, object : OutputStream() { ImageIO.write(this@toExternalImage, formatName, object : OutputStream() {
override fun write(b: Int) { override fun write(b: Int) {
b.toByte().let { b.toByte().let {
this@buildPacket.writeByte(it) this@buildPacket.writeByte(it)
...@@ -31,33 +29,16 @@ fun JavaBufferedImage.toMiraiImage(formatName: String = "gif"): ExternalImage { ...@@ -31,33 +29,16 @@ fun JavaBufferedImage.toMiraiImage(formatName: String = "gif"): ExternalImage {
return ExternalImage(width, height, digest.digest(), formatName, buffer) return ExternalImage(width, height, digest.digest(), formatName, buffer)
} }
fun ExternalImage.toJavaImage(): JavaBufferedImage = ImageIO.read(object : InputStream() { fun File.toExternalImage(): ExternalImage {
override fun read(): Int = with(this@toJavaImage.input) { val input = ImageIO.createImageInputStream(this)
if (!endOfInput) val image = ImageIO.getImageReaders(input).asSequence().firstOrNull() ?: error("Unable to read file(${this.path}), no ImageReader found")
readByte().toInt() image.input = input
else -1
}
})
fun File.toMiraiImage(): ExternalImage {
val image = ImageIO.getImageReaders(this.inputStream()).asSequence().first()
val digest = MessageDigest.getInstance("md5")
digest.reset()
FileInputStream(this).transferTo(object : OutputStream() {
override fun write(b: Int) {
b.toByte().let {
digest.update(it)
}
}
})
val dimension = image.defaultReadParam.sourceRenderSize
return ExternalImage( return ExternalImage(
width = dimension.width, width = image.getWidth(0),
height = dimension.height, height = image.getHeight(0),
md5 = digest.digest(), md5 = this.md5(),
format = image.formatName, imageFormat = image.formatName,
input = this.inputStream().asInput(IoBuffer.Pool), input = this.inputStream().asInput(IoBuffer.Pool),
inputSize = this.length() inputSize = this.length()
) )
......
...@@ -7,16 +7,11 @@ import io.ktor.client.engine.cio.CIO ...@@ -7,16 +7,11 @@ import io.ktor.client.engine.cio.CIO
import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.HttpRequestBuilder
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.http.content.OutgoingContent import io.ktor.http.content.OutgoingContent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.io.ByteWriteChannel import kotlinx.coroutines.io.ByteWriteChannel
import kotlinx.coroutines.io.writeFully
import kotlinx.coroutines.withContext
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Input import kotlinx.io.core.Input
import kotlinx.io.core.readBytes
import kotlinx.io.core.readFully import kotlinx.io.core.readFully
import org.jsoup.Connection import java.io.File
import org.jsoup.Jsoup import java.io.OutputStream
import java.net.InetAddress import java.net.InetAddress
import java.security.MessageDigest import java.security.MessageDigest
import java.util.zip.CRC32 import java.util.zip.CRC32
...@@ -31,56 +26,75 @@ actual fun crc32(key: ByteArray): Int = CRC32().let { it.update(key); it.value.t ...@@ -31,56 +26,75 @@ actual fun crc32(key: ByteArray): Int = CRC32().let { it.update(key); it.value.t
actual fun md5(byteArray: ByteArray): ByteArray = MessageDigest.getInstance("MD5").digest(byteArray) actual fun md5(byteArray: ByteArray): ByteArray = MessageDigest.getInstance("MD5").digest(byteArray)
fun File.md5(): ByteArray {
val digest = MessageDigest.getInstance("md5")
digest.reset()
this.inputStream().transferTo(object : OutputStream() {
override fun write(b: Int) {
b.toByte().let {
digest.update(it)
}
}
})
return digest.digest()
}
actual fun solveIpAddress(hostname: String): String = InetAddress.getByName(hostname).hostAddress actual fun solveIpAddress(hostname: String): String = InetAddress.getByName(hostname).hostAddress
actual fun localIpAddress(): String = InetAddress.getLocalHost().hostAddress actual fun localIpAddress(): String = InetAddress.getLocalHost().hostAddress
suspend fun httpPostFriendImageOld( /*
uKeyHex: String, actual suspend fun httpPostFriendImageOld(
botNumber: UInt, uKeyHex: String,
imageData: ByteReadPacket botNumber: UInt,
): Boolean = Jsoup.connect("http://htdata2.qq.com/cgi-bin/httpconn" + imageData: ByteReadPacket
"?htcmd=0x6ff0070" + ): Boolean = Jsoup.connect(
"&ver=5603" + "http://htdata2.qq.com/cgi-bin/httpconn" +
"&ukey=${uKeyHex}" + "?htcmd=0x6ff0070" +
"&filezise=${imageData.remaining}" + "&ver=5603" +
"&range=0" + "&ukey=$uKeyHex" +
"&uin=$botNumber" "&filezise=${imageData.remaining}" +
"&range=0" +
"&uin=$botNumber"
) )
.postImage(imageData) .postImage(imageData)
private suspend fun Connection.postImage(image: ByteReadPacket): Boolean = this private suspend fun Connection.postImage(image: ByteReadPacket): Boolean = this
.userAgent("QQClient") .userAgent("QQClient")
.header("Content-Length", image.remaining.toString()) .header("Content-Length", image.remaining.toString())
.requestBody(String(image.readBytes(), Charsets.ISO_8859_1)) .requestBody(String(image.readBytes(), Charsets.ISO_8859_1))
.method(Connection.Method.POST) .method(Connection.Method.POST)
.postDataCharset("ISO_8859_1") .postDataCharset("ISO_8859_1")
.header("Content-type", "image/gif") .header("Content-type", "image/gif")
.ignoreContentType(true) .ignoreContentType(true)
.suspendExecute() .suspendExecute()
.statusCode() == 200 .statusCode() == 200
private suspend fun Connection.suspendExecute(): Connection.Response = withContext(Dispatchers.IO) { private suspend fun Connection.suspendExecute(): Connection.Response = withContext(Dispatchers.IO) {
execute() execute()
} }
*/
internal actual val httpClient: HttpClient = HttpClient(CIO) internal actual val httpClient: HttpClient = HttpClient(CIO)
internal actual fun HttpRequestBuilder.configureBody( internal actual fun HttpRequestBuilder.configureBody(
inputSize: Long, inputSize: Long,
input: Input input: Input
) { ) {
body = object : OutgoingContent.WriteChannelContent() { //body = ByteArrayContent(input.readBytes(), ContentType.Image.PNG)
override val contentType: ContentType = ContentType.Image.GIF
override val contentLength: Long = inputSize
body = object : OutgoingContent.WriteChannelContent() {
override suspend fun writeTo(channel: ByteWriteChannel) {//不知道为什么这个 channel 在 common 找不到... override val contentType: ContentType = ContentType.Image.PNG
val buffer = byteArrayOf(1) override val contentLength: Long = inputSize
while (!input.endOfInput) {
input.readFully(buffer) override suspend fun writeTo(channel: ByteWriteChannel) {//不知道为什么这个 channel 在 common 找不到...
channel.writeFully(buffer) val buffer = byteArrayOf(1)
} repeat(contentLength.toInt()) {
} input.readFully(buffer)
channel.writeFully(buffer, 0, buffer.size)
}
} }
}
} }
\ No newline at end of file
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