From c839253e18806fef6e45bec957bd1c0b84cbb480 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 16 Nov 2019 00:48:18 +0800 Subject: [PATCH] Platform specific APIs --- .../kotlin/net.mamoe.mirai/message/Message.kt | 16 +------ .../protocol/tim/packet/event/Message.kt | 28 +++++++++---- .../mamoe/mirai/message/SendImageUtilsJvm.kt | 28 ++++++------- .../tim/packet/event/MessagePacket.kt | 42 +++++++++++++++++++ 4 files changed, 78 insertions(+), 36 deletions(-) create mode 100644 mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/event/MessagePacket.kt diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt index abe4f0714..8a3da8b30 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt @@ -4,10 +4,7 @@ package net.mamoe.mirai.message import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.QQ -import net.mamoe.mirai.network.protocol.tim.packet.action.FriendImageIdRequestPacket -import net.mamoe.mirai.network.protocol.tim.packet.action.download import net.mamoe.mirai.utils.ExternalImage -import net.mamoe.mirai.utils.Http import kotlin.js.JsName import kotlin.jvm.Volatile @@ -165,19 +162,10 @@ inline class Image(inline val id: ImageId) : Message { * 对于好友, [value] 类似于 `/01ee6426-5ff1-4cf0-8278-e8634d2909ef`, 由服务器返回. * * @see ExternalImage.groupImageId 群图片的 [ImageId] 获取 - * @see FriendImageIdRequestPacket.Response.RequireUpload.imageId 好友图片的 [ImageId] 获取 + * @see FriendImagePacket 好友图片的 [ImageId] 获取 */ inline class ImageId(inline val value: String) -/** - * 图片数据地址. - */ -inline class ImageLink(inline val value: String) { - - // TODO: 2019/11/15 应添加更多方法. 避免使用 byte[] - suspend fun downloadAsByteArray(): ByteArray = Http.download(value) -} - fun ImageId.checkLength() = check(value.length == 37 || value.length == 42) { "Illegal ImageId length" } fun ImageId.requireLength() = require(value.length == 37 || value.length == 42) { "Illegal ImageId length" } @@ -281,7 +269,7 @@ fun SingleMessageChain(delegate: Message): MessageChain { * * @see SingleMessageChain * @see SingleMessageChainImpl - */ + */ // TODO: 2019/11/15 有歧义 fun Message.singleChain(): MessageChain = if (this is MessageChain) this else SingleMessageChain(this) /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Message.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Message.kt index 5094afb2d..c7a6e19cc 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Message.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Message.kt @@ -5,28 +5,33 @@ 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.* import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.event.BroadcastControllable 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.internal.readMessageChain import net.mamoe.mirai.network.protocol.tim.packet.PacketVersion -import net.mamoe.mirai.utils.ExternalImage -import net.mamoe.mirai.utils.MiraiLogger +import net.mamoe.mirai.network.protocol.tim.packet.action.FriendImagePacket +import net.mamoe.mirai.network.protocol.tim.packet.action.ImageLink +import net.mamoe.mirai.network.sessionKey +import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.io.printTLVMap import net.mamoe.mirai.utils.io.read import net.mamoe.mirai.utils.io.readTLVMap import net.mamoe.mirai.utils.io.readUShortLVByteArray -import net.mamoe.mirai.utils.sendTo -import net.mamoe.mirai.utils.upload -sealed class MessagePacket : EventPacket, BotEvent() { +/** + * 平台相关扩展 + */ +@UseExperimental(InternalAPI::class) +expect sealed class MessagePacket() : MessagePacketBase + +@InternalAPI +abstract class MessagePacketBase : EventPacket, BotEvent() { internal lateinit var botVar: Bot override val bot: Bot get() = botVar @@ -70,6 +75,13 @@ sealed class MessagePacket : EventPacket, BotEvent() { suspend inline fun String.send() = this.toMessage().sendTo(subject) // endregion + + // region Image download + + suspend fun Image.getLink(): ImageLink = bot.withSession { FriendImagePacket.RequestImageLink(bot.qqAccount, bot.sessionKey, id).sendAndExpect() } + suspend inline fun Image.downloadAsByteArray(): ByteArray = getLink().downloadAsByteArray() + suspend inline fun Image.download(): ByteReadPacket = getLink().download() + // endregion } // region group message diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt index 265a25ac1..be5434f9e 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/SendImageUtilsJvm.kt @@ -75,28 +75,28 @@ suspend fun BufferedImage.upload(contact: Contact): Image = withContext(Dispatch * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun URL.upload(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun URL.uploadAsImage(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Input.upload(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun Input.uploadAsImage(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun InputStream.upload(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) +suspend fun InputStream.uploadAsImage(contact: Contact): Image = withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) /** * 在 [Dispatchers.IO] 中将文件作为图片上传后构造 [Image] * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun File.upload(contact: Contact): Image { +suspend fun File.uploadAsImage(contact: Contact): Image { require(this.exists() && this.canRead()) return withContext(Dispatchers.IO) { toExternalImage() }.upload(contact) } @@ -110,35 +110,35 @@ suspend fun File.upload(contact: Contact): Image { * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.sendImage(bufferedImage: BufferedImage) = bufferedImage.sendTo(this) +suspend inline fun Contact.sendImage(bufferedImage: BufferedImage) = bufferedImage.sendTo(this) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.sendImage(imageUrl: URL) = imageUrl.sendAsImageTo(this) +suspend inline fun Contact.sendImage(imageUrl: URL) = imageUrl.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.sendImage(imageInput: Input) = imageInput.sendAsImageTo(this) +suspend inline fun Contact.sendImage(imageInput: Input) = imageInput.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.sendImage(imageStream: InputStream) = imageStream.sendAsImageTo(this) +suspend inline fun Contact.sendImage(imageStream: InputStream) = imageStream.sendAsImageTo(this) /** * 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.sendImage(file: File) = file.sendAsImageTo(this) +suspend inline fun Contact.sendImage(file: File) = file.sendAsImageTo(this) // endregion @@ -149,34 +149,34 @@ suspend fun Contact.sendImage(file: File) = file.sendAsImageTo(this) * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.uploadImage(bufferedImage: BufferedImage): Image = bufferedImage.upload(this) +suspend inline fun Contact.uploadImage(bufferedImage: BufferedImage): Image = bufferedImage.upload(this) /** * 在 [Dispatchers.IO] 中下载 [URL] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.uploadImage(imageUrl: URL): Image = imageUrl.upload(this) +suspend inline fun Contact.uploadImage(imageUrl: URL): Image = imageUrl.uploadAsImage(this) /** * 在 [Dispatchers.IO] 中读取 [Input] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.uploadImage(imageInput: Input): Image = imageInput.upload(this) +suspend inline fun Contact.uploadImage(imageInput: Input): Image = imageInput.uploadAsImage(this) /** * 在 [Dispatchers.IO] 中读取 [InputStream] 到临时文件并将其作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.uploadImage(imageStream: InputStream): Image = imageStream.upload(this) +suspend inline fun Contact.uploadImage(imageStream: InputStream): Image = imageStream.uploadAsImage(this) /** * 在 [Dispatchers.IO] 中将文件作为图片发送到指定联系人 * @throws OverFileSizeMaxException */ @Throws(OverFileSizeMaxException::class) -suspend fun Contact.uploadImage(file: File): Image = file.upload(this) +suspend inline fun Contact.uploadImage(file: File): Image = file.uploadAsImage(this) // endregion \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/event/MessagePacket.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/event/MessagePacket.kt new file mode 100644 index 000000000..b84fed519 --- /dev/null +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/event/MessagePacket.kt @@ -0,0 +1,42 @@ +@file:Suppress("unused") + +package net.mamoe.mirai.network.protocol.tim.packet.event + +import kotlinx.io.core.Input +import net.mamoe.mirai.contact.Contact +import net.mamoe.mirai.message.* +import net.mamoe.mirai.utils.InternalAPI +import java.awt.image.BufferedImage +import java.io.File +import java.io.InputStream +import java.net.URL + +/** + * 平台相关扩展 + */ +@UseExperimental(InternalAPI::class) +actual sealed class MessagePacket : MessagePacketBase() { + suspend inline fun uploadImage(image: BufferedImage): Image = subject.uploadImage(image) + suspend inline fun uploadImage(image: URL): Image = subject.uploadImage(image) + suspend inline fun uploadImage(image: Input): Image = subject.uploadImage(image) + suspend inline fun uploadImage(image: InputStream): Image = subject.uploadImage(image) + suspend inline fun uploadImage(image: File): Image = subject.uploadImage(image) + + suspend inline fun sendImage(image: BufferedImage) = subject.sendImage(image) + suspend inline fun sendImage(image: URL) = subject.sendImage(image) + suspend inline fun sendImage(image: Input) = subject.sendImage(image) + suspend inline fun sendImage(image: InputStream) = subject.sendImage(image) + suspend inline fun sendImage(image: File) = subject.sendImage(image) + + suspend inline fun BufferedImage.upload(): Image = upload(subject) + suspend inline fun URL.uploadAsImage(): Image = uploadAsImage(subject) + suspend inline fun Input.uploadAsImage(): Image = uploadAsImage(subject) + suspend inline fun InputStream.uploadAsImage(): Image = uploadAsImage(subject) + suspend inline fun File.uploadAsImage(): Image = uploadAsImage(subject) + + suspend inline fun BufferedImage.send() = sendTo(subject) + suspend inline fun URL.sendAsImage() = sendAsImageTo(subject) + suspend inline fun Input.sendAsImage() = sendAsImageTo(subject) + suspend inline fun InputStream.sendAsImage() = sendAsImageTo(subject) + suspend inline fun File.sendAsImage() = sendAsImageTo(subject) +} \ No newline at end of file