mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-13 06:30:13 +08:00
Image download support, close #49
This commit is contained in:
parent
bf1e75eb36
commit
692e7c950c
@ -9,7 +9,9 @@
|
||||
|
||||
package net.mamoe.mirai.qqandroid
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import net.mamoe.mirai.BotAccount
|
||||
import net.mamoe.mirai.BotImpl
|
||||
import net.mamoe.mirai.contact.*
|
||||
@ -17,10 +19,9 @@ import net.mamoe.mirai.data.AddFriendResult
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
import net.mamoe.mirai.data.GroupInfo
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.MessageSource
|
||||
import net.mamoe.mirai.message.data.messageRandom
|
||||
import net.mamoe.mirai.message.data.sequenceId
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.qqandroid.message.CustomFaceFromServer
|
||||
import net.mamoe.mirai.qqandroid.message.NotOnlineImageFromServer
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.GroupInfoImpl
|
||||
@ -150,13 +151,20 @@ internal abstract class QQAndroidBotBase constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun Image.download(): ByteReadPacket {
|
||||
TODO("not implemented")
|
||||
override suspend fun Image.url(): String = "http://gchat.qpic.cn" + when (this) {
|
||||
is NotOnlineImageFromServer -> this.delegate.origUrl
|
||||
is CustomFaceFromServer -> this.delegate.origUrl
|
||||
is CustomFaceFromFile -> {
|
||||
TODO()
|
||||
}
|
||||
is NotOnlineImageFromFile -> {
|
||||
TODO()
|
||||
}
|
||||
else -> error("unsupported image class: ${this::class.simpleName}")
|
||||
}
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
override suspend fun Image.downloadAsByteArray(): ByteArray {
|
||||
TODO("not implemented")
|
||||
override suspend fun Image.channel(): ByteReadChannel {
|
||||
return Http.get<HttpResponse>(url()).content
|
||||
}
|
||||
|
||||
override suspend fun approveFriendAddRequest(id: Long, remark: String?) {
|
||||
|
@ -11,14 +11,11 @@
|
||||
|
||||
package net.mamoe.mirai
|
||||
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.io.OutputStream
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.IoBuffer
|
||||
import kotlinx.io.core.use
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.data.AddFriendResult
|
||||
import net.mamoe.mirai.data.FriendInfo
|
||||
@ -30,7 +27,6 @@ import net.mamoe.mirai.message.data.MessageSource
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.network.LoginFailedException
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.io.transferTo
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.jvm.JvmStatic
|
||||
@ -226,11 +222,12 @@ abstract class Bot : CoroutineScope {
|
||||
abstract suspend fun recall(source: MessageSource)
|
||||
|
||||
/**
|
||||
* 撤回这条消息.
|
||||
* 撤回一条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息.
|
||||
*
|
||||
* [Bot] 撤回自己的消息不需要权限.
|
||||
* [Bot] 撤回群员的消息需要管理员权限.
|
||||
*
|
||||
* @param senderId 这条消息的发送人. 可以为 [Bot.uin] 或 [Member.id]
|
||||
* @param messageId 即 [MessageSource.id]
|
||||
*
|
||||
* @throws PermissionDeniedException 当 [Bot] 无权限操作时
|
||||
@ -239,15 +236,18 @@ abstract class Bot : CoroutineScope {
|
||||
*/
|
||||
abstract suspend fun recall(groupId: Long, senderId: Long, messageId: Long)
|
||||
|
||||
@Deprecated("内存使用效率十分低下", ReplaceWith("this.download()"), DeprecationLevel.WARNING)
|
||||
@MiraiExperimentalAPI("未支持")
|
||||
abstract suspend fun Image.downloadAsByteArray(): ByteArray
|
||||
/**
|
||||
* 获取图片下载链接
|
||||
*/
|
||||
abstract suspend fun Image.url(): String
|
||||
|
||||
/**
|
||||
* 将图片下载到内存中 (使用 [IoBuffer.Pool])
|
||||
* 获取图片下载链接并开始下载.
|
||||
*
|
||||
* @see ByteReadChannel.copyAndClose
|
||||
* @see ByteReadChannel.copyTo
|
||||
*/
|
||||
@MiraiExperimentalAPI("未支持")
|
||||
abstract suspend fun Image.download(): ByteReadPacket
|
||||
abstract suspend fun Image.channel(): ByteReadChannel
|
||||
|
||||
/**
|
||||
* 添加一个好友
|
||||
@ -278,20 +278,7 @@ abstract class Bot : CoroutineScope {
|
||||
*/
|
||||
abstract fun close(cause: Throwable? = null)
|
||||
|
||||
// region extensions
|
||||
|
||||
final override fun toString(): String {
|
||||
return "Bot(${uin})"
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要调用者自行 close [output]
|
||||
*/
|
||||
@MiraiExperimentalAPI("未支持")
|
||||
suspend inline fun Image.downloadTo(output: OutputStream) =
|
||||
download().use { input -> input.transferTo(output) }
|
||||
|
||||
// endregion
|
||||
final override fun toString(): String = "Bot(${uin})"
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,9 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.IoBuffer
|
||||
import kotlinx.io.core.readBytes
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.Group
|
||||
@ -128,20 +126,22 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact> : Packet, Bot
|
||||
// endregion
|
||||
|
||||
// region 下载图片
|
||||
|
||||
|
||||
/**
|
||||
* 将图片下载到内存.
|
||||
* 获取图片下载链接
|
||||
*
|
||||
* 非常不推荐这样做.
|
||||
* @return "http://gchat.qpic.cn/gchatpic_new/..."
|
||||
*/
|
||||
@Deprecated("内存使用效率十分低下", ReplaceWith("this.download()"), DeprecationLevel.WARNING)
|
||||
suspend inline fun Image.downloadAsByteArray(): ByteArray = bot.run { download().readBytes() }
|
||||
|
||||
// TODO: 2020/2/5 为下载图片添加文件系统的存储方式
|
||||
suspend inline fun Image.url(): String = bot.run { url() }
|
||||
|
||||
/**
|
||||
* 将图片下载到内存缓存中 (使用 [IoBuffer.Pool])
|
||||
* 获取图片下载链接并开始下载.
|
||||
*
|
||||
* @see ByteReadChannel.copyAndClose
|
||||
* @see ByteReadChannel.copyTo
|
||||
*/
|
||||
suspend inline fun Image.download(): ByteReadPacket = bot.run { download() }
|
||||
suspend inline fun Image.channel(): ByteReadChannel = bot.run { channel() }
|
||||
// endregion
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ package net.mamoe.mirai.utils
|
||||
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.readAvailable
|
||||
import kotlinx.coroutines.io.close
|
||||
import kotlinx.io.OutputStream
|
||||
import kotlinx.io.core.Output
|
||||
import kotlinx.io.pool.useInstance
|
||||
@ -24,6 +23,7 @@ import net.mamoe.mirai.utils.io.ByteArrayPool
|
||||
import kotlin.jvm.JvmMultifileClass
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
// copyTo
|
||||
|
||||
/**
|
||||
* 从接收者管道读取所有数据并写入 [dst]. 不会关闭 [dst]
|
||||
@ -49,6 +49,8 @@ suspend fun ByteReadChannel.copyTo(dst: Output) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* // 垃圾 kotlin, Unresolved reference: ByteWriteChannel
|
||||
/**
|
||||
* 从接收者管道读取所有数据并写入 [dst]. 不会关闭 [dst]
|
||||
*/
|
||||
@ -60,7 +62,7 @@ suspend fun ByteReadChannel.copyTo(dst: kotlinx.coroutines.io.ByteWriteChannel)
|
||||
} while (size != 0)
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// copyAndClose
|
||||
|
||||
@ -97,18 +99,19 @@ suspend fun ByteReadChannel.copyAndClose(dst: Output) {
|
||||
}
|
||||
}
|
||||
|
||||
/*// 垃圾 kotlin, Unresolved reference: ByteWriteChannel
|
||||
/**
|
||||
* 从接收者管道读取所有数据并写入 [dst], 最终关闭 [dst]
|
||||
*/
|
||||
suspend fun ByteReadChannel.copyAndClose(dst: kotlinx.coroutines.io.ByteWriteChannel) {
|
||||
try {
|
||||
dst.close(kotlin.runCatching {
|
||||
ByteArrayPool.useInstance {
|
||||
do {
|
||||
val size = this.readAvailable(it)
|
||||
dst.writeFully(it, 0, size)
|
||||
} while (size != 0)
|
||||
}
|
||||
} finally {
|
||||
dst.close()
|
||||
}
|
||||
}
|
||||
}.exceptionOrNull())
|
||||
}
|
||||
|
||||
*/
|
@ -11,23 +11,19 @@
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.io.core.Input
|
||||
import kotlinx.io.core.use
|
||||
import kotlinx.io.streams.inputStream
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.utils.ExternalImage
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.toExternalImage
|
||||
import net.mamoe.mirai.utils.copyAndClose
|
||||
import net.mamoe.mirai.utils.copyTo
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.net.URL
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
/**
|
||||
* 一条从服务器接收到的消息事件.
|
||||
@ -72,16 +68,22 @@ actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual con
|
||||
// endregion 发送图片 (扩展)
|
||||
|
||||
// region 下载图片 (扩展)
|
||||
suspend inline fun Image.downloadTo(file: File): Long = file.outputStream().use { downloadTo(it) }
|
||||
suspend inline fun Image.downloadTo(file: File) = file.outputStream().use { downloadTo(it) }
|
||||
|
||||
/**
|
||||
* 这个函数结束后不会关闭 [output]. 请务必解决好 [OutputStream.close]
|
||||
* 下载图片到 [output] 但不关闭这个 [output]
|
||||
*/
|
||||
suspend inline fun Image.downloadTo(output: OutputStream): Long =
|
||||
download().inputStream().use { input -> withContext(Dispatchers.IO) { input.copyTo(output) } }
|
||||
suspend inline fun Image.downloadTo(output: OutputStream) = channel().copyTo(output)
|
||||
|
||||
suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream()
|
||||
suspend inline fun Image.downloadAsExternalImage(): ExternalImage = withContext(Dispatchers.IO) { download().toExternalImage() }
|
||||
/**
|
||||
* 下载图片到 [output] 并关闭这个 [output]
|
||||
*/
|
||||
suspend inline fun Image.downloadAndClose(output: OutputStream) = channel().copyAndClose(output)
|
||||
|
||||
/*
|
||||
suspend inline fun Image.downloadAsStream(): InputStream = channel().asInputStream()
|
||||
suspend inline fun Image.downloadAsExternalImage(): ExternalImage = withContext(Dispatchers.IO) { downloadAsStream().toExternalImage() }
|
||||
suspend inline fun Image.downloadAsBufferedImage(): BufferedImage = withContext(Dispatchers.IO) { ImageIO.read(downloadAsStream()) }
|
||||
*/
|
||||
// endregion
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package net.mamoe.mirai.japt;
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket;
|
||||
import net.mamoe.mirai.Bot;
|
||||
import net.mamoe.mirai.BotAccount;
|
||||
import net.mamoe.mirai.BotFactoryJvmKt;
|
||||
@ -153,18 +152,16 @@ public interface BlockingBot {
|
||||
|
||||
// region actions
|
||||
|
||||
@NotNull
|
||||
byte[] downloadAsByteArray(@NotNull Image image);
|
||||
|
||||
@NotNull
|
||||
ByteReadPacket download(@NotNull Image image);
|
||||
|
||||
/**
|
||||
* 下载图片到 {@code outputStream}.
|
||||
* <p>
|
||||
* 不会自动关闭 {@code outputStream}
|
||||
*/
|
||||
void download(@NotNull Image image, @NotNull OutputStream outputStream);
|
||||
void downloadTo(@NotNull Image image, @NotNull OutputStream outputStream);
|
||||
|
||||
/**
|
||||
* 下载图片到 {@code outputStream} 并关闭 stream
|
||||
*/
|
||||
void downloadAndClose(@NotNull Image image, @NotNull OutputStream outputStream);
|
||||
|
||||
/**
|
||||
* 添加一个好友
|
||||
|
@ -10,8 +10,6 @@
|
||||
package net.mamoe.mirai.japt.internal
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.readBytes
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.BotAccount
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
@ -23,10 +21,7 @@ import net.mamoe.mirai.japt.BlockingGroup
|
||||
import net.mamoe.mirai.japt.BlockingQQ
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.toList
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.io.OutputStream
|
||||
import java.util.stream.Stream
|
||||
import kotlin.streams.asStream
|
||||
@ -59,10 +54,8 @@ internal class BlockingBotImpl(private val bot: Bot) : BlockingBot {
|
||||
override fun getGroup(id: Long): BlockingGroup = runBlocking { bot.getGroup(id).blocking() }
|
||||
override fun getNetwork(): BotNetworkHandler = bot.network
|
||||
override fun login() = runBlocking { bot.login() }
|
||||
override fun downloadAsByteArray(image: Image): ByteArray = bot.run { runBlocking { image.download().readBytes() } }
|
||||
override fun download(image: Image): ByteReadPacket = bot.run { runBlocking { image.download() } }
|
||||
override fun download(image: Image, outputStream: OutputStream) = bot.run { runBlocking { image.downloadTo(outputStream) } }
|
||||
|
||||
override fun downloadTo(image: Image, outputStream: OutputStream) = bot.run { runBlocking { image.channel().copyTo(outputStream) } }
|
||||
override fun downloadAndClose(image: Image, outputStream: OutputStream) = bot.run { runBlocking { image.channel().copyAndClose(outputStream) } }
|
||||
override fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult = runBlocking { bot.addFriend(id, message, remark) }
|
||||
override fun approveFriendAddRequest(id: Long, remark: String?) = runBlocking { bot.approveFriendAddRequest(id, remark) }
|
||||
override fun close(throwable: Throwable?) = bot.close(throwable)
|
||||
|
Loading…
Reference in New Issue
Block a user