From bc1cce313fafeda110a90bdfab423c097a79078e Mon Sep 17 00:00:00 2001 From: Him188 Date: Mon, 6 Dec 2021 15:23:27 +0000 Subject: [PATCH] Support `AbsoluteFolder.resolveFolderById` (#1712) * Support `AbsoluteFolder.resolveFolderById` * resolveFolderById: Always return null when receiver is not root and id is not root --- ...binary-compatibility-validator-android.api | 2 + .../api/binary-compatibility-validator.api | 2 + .../kotlin/contact/file/AbsoluteFolder.kt | 9 ++++ .../kotlin/contact/file/AbsoluteFolderImpl.kt | 13 +++++ .../kotlin/contact/file/AbsoluteFolderTest.kt | 50 +++++++++++++++++++ 5 files changed, 76 insertions(+) create mode 100644 mirai-core/src/commonTest/kotlin/contact/file/AbsoluteFolderTest.kt diff --git a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api index 866d647c9..ef63378e7 100644 --- a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api +++ b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api @@ -849,6 +849,8 @@ public abstract interface class net/mamoe/mirai/contact/file/AbsoluteFolder : ne public abstract fun resolveFilesStream (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun resolveFolder (Ljava/lang/String;)Lnet/mamoe/mirai/contact/file/AbsoluteFolder; public abstract fun resolveFolder (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun resolveFolderById (Ljava/lang/String;)Lnet/mamoe/mirai/contact/file/AbsoluteFolder; + public abstract fun resolveFolderById (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun uploadNewFile (Ljava/lang/String;Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/contact/file/AbsoluteFile; public fun uploadNewFile (Ljava/lang/String;Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun uploadNewFile (Ljava/lang/String;Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/utils/ProgressionCallback;)Lnet/mamoe/mirai/contact/file/AbsoluteFile; diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api index dc1438c42..258074e31 100644 --- a/binary-compatibility-validator/api/binary-compatibility-validator.api +++ b/binary-compatibility-validator/api/binary-compatibility-validator.api @@ -849,6 +849,8 @@ public abstract interface class net/mamoe/mirai/contact/file/AbsoluteFolder : ne public abstract fun resolveFilesStream (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun resolveFolder (Ljava/lang/String;)Lnet/mamoe/mirai/contact/file/AbsoluteFolder; public abstract fun resolveFolder (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun resolveFolderById (Ljava/lang/String;)Lnet/mamoe/mirai/contact/file/AbsoluteFolder; + public abstract fun resolveFolderById (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun uploadNewFile (Ljava/lang/String;Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/contact/file/AbsoluteFile; public fun uploadNewFile (Ljava/lang/String;Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun uploadNewFile (Ljava/lang/String;Lnet/mamoe/mirai/utils/ExternalResource;Lnet/mamoe/mirai/utils/ProgressionCallback;)Lnet/mamoe/mirai/contact/file/AbsoluteFile; diff --git a/mirai-core-api/src/commonMain/kotlin/contact/file/AbsoluteFolder.kt b/mirai-core-api/src/commonMain/kotlin/contact/file/AbsoluteFolder.kt index 3d46ec6b1..aa441e742 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/file/AbsoluteFolder.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/file/AbsoluteFolder.kt @@ -119,6 +119,15 @@ public interface AbsoluteFolder : AbsoluteFileFolder { */ public suspend fun resolveFolder(name: String): AbsoluteFolder? + /** + * 获取一个已存在的 [AbsoluteFileFolder.id] 为 [id] 的子目录. 当该名称的子目录不存在时返回 `null`. + * + * @throws IllegalArgumentException 当 [id] 为空或无效时抛出 + * + * @since 2.9.0 + */ + public suspend fun resolveFolderById(id: String): AbsoluteFolder? + /** * 精确获取 [AbsoluteFile.id] 为 [id] 的文件. 在目标文件不存在时返回 `null`. 当 [deep] 为 `true` 时还会深入子目录查找. */ diff --git a/mirai-core/src/commonMain/kotlin/contact/file/AbsoluteFolderImpl.kt b/mirai-core/src/commonMain/kotlin/contact/file/AbsoluteFolderImpl.kt index 81ad72ff3..45a26196f 100644 --- a/mirai-core/src/commonMain/kotlin/contact/file/AbsoluteFolderImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/file/AbsoluteFolderImpl.kt @@ -369,6 +369,19 @@ internal class AbsoluteFolderImpl( return getItemsFlow().firstOrNull { it.folderInfo?.folderName == name }?.resolve() as AbsoluteFolder? } + override suspend fun resolveFolderById(id: String): AbsoluteFolder? { + if (name.isBlank()) throw IllegalArgumentException("folder id cannot be blank.") + if (!FileSystem.isLegal(id)) return null + if (id == AbsoluteFolder.ROOT_FOLDER_ID) return root // special case, not ambiguous — '/' always refers to root. + if (this.id != AbsoluteFolder.ROOT_FOLDER_ID) return null // reserved for future + + // All folder ids start with '/'. + // Currently, only root folders can have children folders, + // and we don't know how the folderIds can be changed, + // so we force the receiver to be root for now, to provide forward-compatibility. + return root.impl().getItemsFlow().firstOrNull { it.folderInfo?.folderId == id }?.resolve() as AbsoluteFolder? + } + override suspend fun resolveFileById(id: String, deep: Boolean): AbsoluteFile? { if (id == "/" || id.isEmpty()) throw IllegalArgumentException("Illegal file id: $id") getItemsFlow().filter { it.fileInfo?.fileId == id }.map { it.resolve() as AbsoluteFile }.firstOrNull() diff --git a/mirai-core/src/commonTest/kotlin/contact/file/AbsoluteFolderTest.kt b/mirai-core/src/commonTest/kotlin/contact/file/AbsoluteFolderTest.kt new file mode 100644 index 000000000..b69cc9a7d --- /dev/null +++ b/mirai-core/src/commonTest/kotlin/contact/file/AbsoluteFolderTest.kt @@ -0,0 +1,50 @@ +/* + * 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. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +@file:JvmBlockingBridge + +package net.mamoe.mirai.internal.contact.file + +import net.mamoe.kjbb.JvmBlockingBridge +import net.mamoe.mirai.internal.MockBot +import net.mamoe.mirai.internal.network.notice.BotAware +import net.mamoe.mirai.internal.network.protocol.data.proto.GroupFileCommon +import net.mamoe.mirai.internal.notice.processors.GroupExtensions +import net.mamoe.mirai.internal.test.AbstractTest +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +internal class AbsoluteFolderTest : AbstractTest(), BotAware, GroupExtensions { + override val bot = MockBot { } + val group = bot.addGroup(1L, 2L) + private val root = group.files.root + + @Test + suspend fun `resolveFolderById always returns null if it is not root`() { + val child = root.impl().createChildFolder( + GroupFileCommon.FolderInfo( + folderId = "/f-1", + folderName = "name" + ) + ) + assertEquals(null, child.resolveFolderById("/anything")) + } + + @Test + suspend fun `resolveFolderById always returns root for slash`() { + val child = root.impl().createChildFolder( + GroupFileCommon.FolderInfo( + folderId = "/f-1", + folderName = "name" + ) + ) + assertEquals(root, root.resolveFolderById("/")) + assertEquals(root, child.resolveFolderById("/")) + } +} \ No newline at end of file