Introduce auto close for ExternalResource

This commit is contained in:
Him188 2021-07-05 19:09:10 +08:00
parent f239192677
commit 4d0afc27dc
7 changed files with 104 additions and 20 deletions

View File

@ -5625,12 +5625,14 @@ public abstract interface class net/mamoe/mirai/utils/ExternalResource : java/io
public static fun create (Ljava/io/RandomAccessFile;Ljava/lang/String;Z)Lnet/mamoe/mirai/utils/ExternalResource;
public static fun create ([B)Lnet/mamoe/mirai/utils/ExternalResource;
public static fun create ([BLjava/lang/String;)Lnet/mamoe/mirai/utils/ExternalResource;
public static fun createAutoCloseable (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/utils/ExternalResource;
public abstract fun getClosed ()Lkotlinx/coroutines/Deferred;
public abstract fun getFormatName ()Ljava/lang/String;
public abstract fun getMd5 ()[B
public fun getSha1 ()[B
public abstract fun getSize ()J
public abstract fun inputStream ()Ljava/io/InputStream;
public fun isAutoClose ()Z
public static fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public static fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;)Lnet/mamoe/mirai/message/MessageReceipt;
@ -5686,6 +5688,7 @@ public final class net/mamoe/mirai/utils/ExternalResource$Companion {
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/InputStream;Ljava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/ExternalResource;
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/RandomAccessFile;Ljava/lang/String;ZILjava/lang/Object;)Lnet/mamoe/mirai/utils/ExternalResource;
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;[BLjava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/ExternalResource;
public final fun createAutoCloseable (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/utils/ExternalResource;
public final fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public final fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;)Lnet/mamoe/mirai/message/MessageReceipt;
@ -5742,6 +5745,11 @@ public final class net/mamoe/mirai/utils/ExternalResource$Companion {
public static synthetic fun uploadTo$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
}
public final class net/mamoe/mirai/utils/ExternalResourceKt {
public static final fun runAutoClose (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun useAutoClose (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}
public abstract interface class net/mamoe/mirai/utils/FileCacheStrategy {
public static final field Companion Lnet/mamoe/mirai/utils/FileCacheStrategy$Companion;
public static fun getPlatformDefault ()Lnet/mamoe/mirai/utils/FileCacheStrategy;

View File

@ -5625,12 +5625,14 @@ public abstract interface class net/mamoe/mirai/utils/ExternalResource : java/io
public static fun create (Ljava/io/RandomAccessFile;Ljava/lang/String;Z)Lnet/mamoe/mirai/utils/ExternalResource;
public static fun create ([B)Lnet/mamoe/mirai/utils/ExternalResource;
public static fun create ([BLjava/lang/String;)Lnet/mamoe/mirai/utils/ExternalResource;
public static fun createAutoCloseable (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/utils/ExternalResource;
public abstract fun getClosed ()Lkotlinx/coroutines/Deferred;
public abstract fun getFormatName ()Ljava/lang/String;
public abstract fun getMd5 ()[B
public fun getSha1 ()[B
public abstract fun getSize ()J
public abstract fun inputStream ()Ljava/io/InputStream;
public fun isAutoClose ()Z
public static fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public static fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;)Lnet/mamoe/mirai/message/MessageReceipt;
@ -5686,6 +5688,7 @@ public final class net/mamoe/mirai/utils/ExternalResource$Companion {
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/InputStream;Ljava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/ExternalResource;
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/RandomAccessFile;Ljava/lang/String;ZILjava/lang/Object;)Lnet/mamoe/mirai/utils/ExternalResource;
public static synthetic fun create$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;[BLjava/lang/String;ILjava/lang/Object;)Lnet/mamoe/mirai/utils/ExternalResource;
public final fun createAutoCloseable (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/utils/ExternalResource;
public final fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public final fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun sendAsFile (Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;)Lnet/mamoe/mirai/message/MessageReceipt;
@ -5742,6 +5745,11 @@ public final class net/mamoe/mirai/utils/ExternalResource$Companion {
public static synthetic fun uploadTo$default (Lnet/mamoe/mirai/utils/ExternalResource$Companion;Ljava/io/File;Lnet/mamoe/mirai/contact/FileSupported;Ljava/lang/String;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
}
public final class net/mamoe/mirai/utils/ExternalResourceKt {
public static final fun runAutoClose (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun useAutoClose (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}
public abstract interface class net/mamoe/mirai/utils/FileCacheStrategy {
public static final field Companion Lnet/mamoe/mirai/utils/FileCacheStrategy$Companion;
public static fun getPlatformDefault ()Lnet/mamoe/mirai/utils/FileCacheStrategy;

View File

@ -32,6 +32,8 @@ import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsImage
import net.mamoe.mirai.utils.RemoteFile.Companion.sendFile
import net.mamoe.mirai.utils.RemoteFile.Companion.uploadFile
import java.io.*
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
/**
@ -67,6 +69,19 @@ import java.io.*
*/
public interface ExternalResource : Closeable {
/**
* 是否在 _使用一次_ 后自动 [close].
*
* 该属性仅供调用方参考. [Contact.uploadImage] 会在方法结束时关闭 [isAutoClose] `true` [ExternalResource], 无论上传图片是否成功.
*
* 所有 mirai 内置的上传图片, 上传语音等方法都支持该行为.
*
* @since 2.8
*/
@MiraiExperimentalApi
public val isAutoClose: Boolean
get() = false
/**
* 文件内容 MD5. 16 bytes
*/
@ -188,6 +203,23 @@ public interface ExternalResource : Closeable {
public fun InputStream.toExternalResource(formatName: String? = null): ExternalResource =
Mirai.FileCacheStrategy.newCache(this, formatName)
/**
* 创建一个在 _使用一次_ 后就会自动 [close] [ExternalResource].
*
* @since 2.8
*/
@JvmName("createAutoCloseable")
@JvmStatic
public fun ExternalResource.toAutoCloseable(): ExternalResource {
return if (isAutoClose) this else {
val delegate = this
object : ExternalResource by delegate {
override val isAutoClose: Boolean get() = true
override fun toString(): String = "ExternalResourceWithAutoClose(delegate=$delegate)"
}
}
}
// endregion
///////////////////////////////////////////////////////////////////////////
@ -427,3 +459,41 @@ public interface ExternalResource : Closeable {
// endregion
}
}
/**
* 执行 [action], 如果 [ExternalResource.isAutoClose], 在执行完成后调用 [ExternalResource.close].
*
* @since 2.8
*/
@MiraiExperimentalApi
// Continuing mark it as experimental until Kotlin's contextual receivers design is published.
// We might be able to make `action` a type `context(ExternalResource) () -> R`.
public inline fun <T : ExternalResource, R> T.withAutoClose(action: () -> R): R {
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
trySafely(
block = { return action() },
finally = { if (isAutoClose) close() }
)
}
/**
* 执行 [action], 如果 [ExternalResource.isAutoClose], 在执行完成后调用 [ExternalResource.close].
*
* @since 2.8
*/
@MiraiExperimentalApi
public inline fun <T : ExternalResource, R> T.runAutoClose(action: T.() -> R): R {
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
return withAutoClose { action() }
}
/**
* 执行 [action], 如果 [ExternalResource.isAutoClose], 在执行完成后调用 [ExternalResource.close].
*
* @since 2.8
*/
@MiraiExperimentalApi
public inline fun <T : ExternalResource, R> T.useAutoClose(action: (resource: T) -> R): R {
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
return runAutoClose(action)
}

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal.contact
@ -73,7 +73,7 @@ internal sealed class AbstractUser(
open val info: UserInfo = userInfo
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
override suspend fun uploadImage(resource: ExternalResource): Image {
override suspend fun uploadImage(resource: ExternalResource): Image = resource.withAutoClose {
if (BeforeImageUploadEvent(this, resource).broadcast().isCancelled) {
throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup")
}

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:OptIn(LowLevelApi::class)
@ -28,15 +28,13 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.PttStore
import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.audioCodec
import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList
import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.OfflineAudio
import net.mamoe.mirai.utils.ExternalResource
import net.mamoe.mirai.utils.recoverCatchingSuppressed
import net.mamoe.mirai.utils.toByteArray
import net.mamoe.mirai.utils.toUHexString
import net.mamoe.mirai.utils.*
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext
@ -83,7 +81,7 @@ internal class FriendImpl(
override fun toString(): String = "Friend($id)"
override suspend fun uploadAudio(resource: ExternalResource): OfflineAudio = bot.network.run {
override suspend fun uploadAudio(resource: ExternalResource): OfflineAudio = resource.withAutoClose {
var audio: OfflineAudioImpl? = null
kotlin.runCatching {
val resp = Highway.uploadResourceBdh(
@ -115,7 +113,7 @@ internal class FriendImpl(
)
)
}.recoverCatchingSuppressed {
when (val resp = PttStore.GroupPttUp(bot.client, bot.id, id, resource).sendAndExpect<Any>()) {
when (val resp = PttStore.GroupPttUp(bot.client, bot.id, id, resource).sendAndExpect(bot)) {
is PttStore.GroupPttUp.Response.RequireUpload -> {
tryServersUpload(
bot,

View File

@ -166,7 +166,7 @@ internal class GroupImpl constructor(
}
@OptIn(ExperimentalTime::class)
override suspend fun uploadImage(resource: ExternalResource): Image {
override suspend fun uploadImage(resource: ExternalResource): Image = resource.withAutoClose {
if (BeforeImageUploadEvent(this, resource).broadcast().isCancelled) {
throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup")
}
@ -217,7 +217,7 @@ internal class GroupImpl constructor(
}
@Suppress("OverridingDeprecatedMember", "DEPRECATION")
override suspend fun uploadVoice(resource: ExternalResource): Voice {
override suspend fun uploadVoice(resource: ExternalResource): Voice = resource.withAutoClose {
return bot.network.run {
uploadAudioResource(resource)
@ -262,7 +262,7 @@ internal class GroupImpl constructor(
}.getOrThrow()
}
override suspend fun uploadAudio(resource: ExternalResource): OfflineAudio {
override suspend fun uploadAudio(resource: ExternalResource): OfflineAudio = resource.withAutoClose {
return bot.network.run {
uploadAudioResource(resource)

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal.utils
@ -440,7 +440,7 @@ internal class RemoteFileImpl(
private suspend fun upload0(
resource: ExternalResource,
callback: RemoteFile.ProgressionCallback?,
): Oidb0x6d6.UploadFileRspBody? {
): Oidb0x6d6.UploadFileRspBody? = resource.withAutoClose {
val parent = parent ?: return null
val parentInfo = parent.getFileFolderInfo() ?: return null
val resp = FileManagement.RequestUpload(