From 16609fb1e01d9c3cea24f63c2a74da5bd8bdc40e Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 25 Sep 2022 23:44:18 +0800 Subject: [PATCH] =?UTF-8?q?[core]=20Introduce=20`Streamable`=20for=20simpl?= =?UTF-8?q?ified=20multiplatform=20`asFlow`=20a=E2=80=A6=20(#2256)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [core] Introduce `Streamable` for simplified multiplatform `asFlow` and `asStream`. Make `Announcements.asFlow` not suspend. * Remove `@JvmBlockingBridge` in native --- .../android/api/android.api | 22 ++- .../compatibility-validation/jvm/api/jvm.api | 22 ++- .../kotlin/contact/active/GroupActive.kt | 11 +- .../contact/announcement/Announcements.kt | 42 ++--- .../src/commonMain/kotlin/utils/Streamable.kt | 41 +++++ .../kotlin/contact/active/GroupActive.kt | 172 ------------------ .../contact/announcement/Announcements.kt | 110 ----------- .../jvmBaseMain/kotlin/utils/Streamable.kt | 50 +++++ .../kotlin/contact/active/GroupActive.kt | 154 ---------------- .../contact/announcement/Announcements.kt | 95 ---------- .../src/nativeMain/kotlin/utils/Streamable.kt | 39 ++++ .../internal/contact/MockAnnouncementsImpl.kt | 2 +- .../contact/announcement/AnnouncementsImpl.kt | 4 +- .../network/highway/ChunkedFlowSession.kt | 2 +- 14 files changed, 180 insertions(+), 586 deletions(-) create mode 100644 mirai-core-api/src/commonMain/kotlin/utils/Streamable.kt delete mode 100644 mirai-core-api/src/jvmBaseMain/kotlin/contact/active/GroupActive.kt delete mode 100644 mirai-core-api/src/jvmBaseMain/kotlin/contact/announcement/Announcements.kt create mode 100644 mirai-core-api/src/jvmBaseMain/kotlin/utils/Streamable.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/contact/active/GroupActive.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/contact/announcement/Announcements.kt create mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/Streamable.kt diff --git a/mirai-core-api/compatibility-validation/android/api/android.api b/mirai-core-api/compatibility-validation/android/api/android.api index 36999dc4d..1688ec509 100644 --- a/mirai-core-api/compatibility-validation/android/api/android.api +++ b/mirai-core-api/compatibility-validation/android/api/android.api @@ -660,9 +660,7 @@ public final class net/mamoe/mirai/contact/active/ActiveRecord { public final fun getPeriodDays ()I } -public abstract interface class net/mamoe/mirai/contact/active/GroupActive { - public abstract fun asFlow ()Lkotlinx/coroutines/flow/Flow; - public abstract fun asStream ()Ljava/util/stream/Stream; +public abstract interface class net/mamoe/mirai/contact/active/GroupActive : net/mamoe/mirai/utils/Streamable { public abstract fun getRankTitles ()Ljava/util/Map; public abstract fun getTemperatureTitles ()Ljava/util/Map; public abstract fun isHonorVisible ()Z @@ -837,19 +835,15 @@ public final class net/mamoe/mirai/contact/announcement/AnnouncementParametersBu public static final fun buildAnnouncementParameters (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/contact/announcement/AnnouncementParameters; } -public abstract interface class net/mamoe/mirai/contact/announcement/Announcements { - public fun asFlow ()Lkotlinx/coroutines/flow/Flow; - public abstract fun asFlow (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun asStream ()Ljava/util/stream/Stream; +public abstract interface class net/mamoe/mirai/contact/announcement/Announcements : net/mamoe/mirai/utils/Streamable { + public synthetic fun asFlow (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun asFlow (Lnet/mamoe/mirai/contact/announcement/Announcements;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun delete (Ljava/lang/String;)Z public abstract fun delete (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun get (Ljava/lang/String;)Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement; public abstract fun get (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun publish (Lnet/mamoe/mirai/contact/announcement/Announcement;)Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement; public abstract fun publish (Lnet/mamoe/mirai/contact/announcement/Announcement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun toList ()Ljava/util/List; - public fun toList (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun toList$suspendImpl (Lnet/mamoe/mirai/contact/announcement/Announcements;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/contact/announcement/AnnouncementImage; public abstract fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } @@ -6163,6 +6157,14 @@ public final class net/mamoe/mirai/utils/SingleFileLogger : net/mamoe/mirai/util public fun warning (Ljava/lang/Throwable;)V } +public abstract interface class net/mamoe/mirai/utils/Streamable { + public abstract fun asFlow ()Lkotlinx/coroutines/flow/Flow; + public abstract fun asStream ()Ljava/util/stream/Stream; + public fun toList ()Ljava/util/List; + public fun toList (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun toList$suspendImpl (Lnet/mamoe/mirai/utils/Streamable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + public final class net/mamoe/mirai/utils/Utils { public static final synthetic fun BotConfiguration (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/utils/BotConfiguration; public static final fun debug (Lnet/mamoe/mirai/utils/MiraiLogger;Lkotlin/jvm/functions/Function0;)V diff --git a/mirai-core-api/compatibility-validation/jvm/api/jvm.api b/mirai-core-api/compatibility-validation/jvm/api/jvm.api index 6633e10d9..7a6c174ea 100644 --- a/mirai-core-api/compatibility-validation/jvm/api/jvm.api +++ b/mirai-core-api/compatibility-validation/jvm/api/jvm.api @@ -660,9 +660,7 @@ public final class net/mamoe/mirai/contact/active/ActiveRecord { public final fun getPeriodDays ()I } -public abstract interface class net/mamoe/mirai/contact/active/GroupActive { - public abstract fun asFlow ()Lkotlinx/coroutines/flow/Flow; - public abstract fun asStream ()Ljava/util/stream/Stream; +public abstract interface class net/mamoe/mirai/contact/active/GroupActive : net/mamoe/mirai/utils/Streamable { public abstract fun getRankTitles ()Ljava/util/Map; public abstract fun getTemperatureTitles ()Ljava/util/Map; public abstract fun isHonorVisible ()Z @@ -837,19 +835,15 @@ public final class net/mamoe/mirai/contact/announcement/AnnouncementParametersBu public static final fun buildAnnouncementParameters (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/contact/announcement/AnnouncementParameters; } -public abstract interface class net/mamoe/mirai/contact/announcement/Announcements { - public fun asFlow ()Lkotlinx/coroutines/flow/Flow; - public abstract fun asFlow (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun asStream ()Ljava/util/stream/Stream; +public abstract interface class net/mamoe/mirai/contact/announcement/Announcements : net/mamoe/mirai/utils/Streamable { + public synthetic fun asFlow (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun asFlow (Lnet/mamoe/mirai/contact/announcement/Announcements;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun delete (Ljava/lang/String;)Z public abstract fun delete (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun get (Ljava/lang/String;)Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement; public abstract fun get (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun publish (Lnet/mamoe/mirai/contact/announcement/Announcement;)Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement; public abstract fun publish (Lnet/mamoe/mirai/contact/announcement/Announcement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun toList ()Ljava/util/List; - public fun toList (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun toList$suspendImpl (Lnet/mamoe/mirai/contact/announcement/Announcements;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/contact/announcement/AnnouncementImage; public abstract fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } @@ -6159,6 +6153,14 @@ public final class net/mamoe/mirai/utils/StandardCharImageLoginSolver$Companion public final fun createBlocking (Lkotlin/jvm/functions/Function0;Lnet/mamoe/mirai/utils/MiraiLogger;)Lnet/mamoe/mirai/utils/StandardCharImageLoginSolver; } +public abstract interface class net/mamoe/mirai/utils/Streamable { + public abstract fun asFlow ()Lkotlinx/coroutines/flow/Flow; + public abstract fun asStream ()Ljava/util/stream/Stream; + public fun toList ()Ljava/util/List; + public fun toList (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun toList$suspendImpl (Lnet/mamoe/mirai/utils/Streamable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + public final class net/mamoe/mirai/utils/Utils { public static final synthetic fun BotConfiguration (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/utils/BotConfiguration; public static final fun debug (Lnet/mamoe/mirai/utils/MiraiLogger;Lkotlin/jvm/functions/Function0;)V diff --git a/mirai-core-api/src/commonMain/kotlin/contact/active/GroupActive.kt b/mirai-core-api/src/commonMain/kotlin/contact/active/GroupActive.kt index 46c266956..116da6403 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/active/GroupActive.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/active/GroupActive.kt @@ -11,12 +11,12 @@ package net.mamoe.mirai.contact.active -import kotlinx.coroutines.flow.Flow import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Member import net.mamoe.mirai.data.GroupHonorType import net.mamoe.mirai.utils.NotStableForInheritance +import net.mamoe.mirai.utils.Streamable import kotlin.jvm.JvmName /** @@ -62,7 +62,7 @@ import kotlin.jvm.JvmName * @since 2.13 */ @NotStableForInheritance -public expect interface GroupActive { +public interface GroupActive : Streamable { /** * 是否在群聊中显示荣誉 @@ -133,13 +133,6 @@ public expect interface GroupActive { */ public suspend fun refresh() - /** - * 创建一个能获取该群内所有群活跃度记录的 [Flow]. 在 [Flow] 被使用时才会分页下载 [ActiveRecord]. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [ActiveRecord] 和 [Flow] 的[收集][Flow.collect]. - */ - public fun asFlow(): Flow - /** * 获取活跃度图表数据 */ diff --git a/mirai-core-api/src/commonMain/kotlin/contact/announcement/Announcements.kt b/mirai-core-api/src/commonMain/kotlin/contact/announcement/Announcements.kt index 1f53daedf..3863dce26 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/announcement/Announcements.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/announcement/Announcements.kt @@ -7,15 +7,17 @@ * https://github.com/mamoe/mirai/blob/dev/LICENSE */ -@file:Suppress("INAPPLICABLE_JVM_NAME") - package net.mamoe.mirai.contact.announcement import kotlinx.coroutines.flow.Flow +import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.PermissionDeniedException +import net.mamoe.mirai.utils.DeprecatedSinceMirai import net.mamoe.mirai.utils.ExternalResource import net.mamoe.mirai.utils.NotStableForInheritance +import net.mamoe.mirai.utils.Streamable +import kotlin.jvm.JvmName /** @@ -29,7 +31,7 @@ import net.mamoe.mirai.utils.NotStableForInheritance * * ### 获取公告列表 * - * 通过 [asFlow] 或 [asStream] 可以获取到*惰性*流, 在从流中收集数据时才会请求服务器获取数据. 通常建议在 Kotlin 使用协程的 [asFlow], 在 Java 使用 [asStream]. + * 通过 [asFlow] 或 `asStream` 可以获取到*惰性*流, 在从流中收集数据时才会请求服务器获取数据. 通常建议在 Kotlin 使用协程的 [asFlow], 在 Java 使用 `asStream`. * * 若要获取全部公告列表, 可使用 [toList]. * @@ -40,24 +42,7 @@ import net.mamoe.mirai.utils.NotStableForInheritance * @since 2.7 */ @NotStableForInheritance -public expect interface Announcements { - /** - * 创建一个能获取该群内所有群公告列表的 [Flow]. 在 [Flow] 被使用时才会分页下载 [OnlineAnnouncement]. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [OfflineAnnouncement] 和 [Flow] 的[收集][Flow.collect]. - */ - public suspend fun asFlow(): Flow - - /** - * 获取所有群公告列表, 将全部 [OnlineAnnouncement] 都下载后再返回. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取并返回已经成功获取到的 [OfflineAnnouncement] 列表. - * - * @return 此时刻的群公告只读列表. - */ - public open suspend fun toList(): List - - +public interface Announcements : Streamable { /** * 删除一条群公告. 需要管理员权限. 使用 [OnlineAnnouncement.delete] 与此方法效果相同. * @@ -69,6 +54,7 @@ public expect interface Announcements { * * @see OnlineAnnouncement.delete */ + @JvmBlockingBridge public suspend fun delete(fid: String): Boolean /** @@ -77,6 +63,7 @@ public expect interface Announcements { * @return 返回 `null` 表示不存在该 [fid] 的群公告 * @throws IllegalStateException 当协议异常时抛出 */ + @JvmBlockingBridge public suspend fun get(fid: String): OnlineAnnouncement? /** @@ -85,6 +72,7 @@ public expect interface Announcements { * @throws IllegalStateException 当协议异常时抛出 * @see Announcement.publishTo */ + @JvmBlockingBridge public suspend fun publish(announcement: Announcement): OnlineAnnouncement /** @@ -93,5 +81,17 @@ public expect interface Announcements { * **注意**: 需要由调用方[关闭][ExternalResource.close] [resource]. * @throws IllegalStateException 当协议异常时抛出 */ + @JvmBlockingBridge public suspend fun uploadImage(resource: ExternalResource): AnnouncementImage + + + // no blocking bridge for this method + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("asFlow") + @Deprecated( + "Kept for binary compatibility. Use non-suspend overload instead.", + level = DeprecationLevel.HIDDEN + ) + @DeprecatedSinceMirai(hiddenSince = "2.13") + public suspend fun asFlow0(): Flow = asFlow() } diff --git a/mirai-core-api/src/commonMain/kotlin/utils/Streamable.kt b/mirai-core-api/src/commonMain/kotlin/utils/Streamable.kt new file mode 100644 index 000000000..f702e2087 --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/utils/Streamable.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2019-2022 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.utils + +import kotlinx.coroutines.flow.Flow +import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge +import net.mamoe.mirai.contact.announcement.Announcements +import net.mamoe.mirai.contact.announcement.OnlineAnnouncement + +/** + * 表示一个可以创建[数据流][Flow]的对象. + * + * 实现这个接口的对象可以看做为元素 [T] 的集合. + * 例如 [Announcements] 可以看作是 [OnlineAnnouncement] 的集合, + * 使用 [Announcements.asFlow] 可以获取到包含所有 [OnlineAnnouncement] 列表的 [Flow] + * 在 JVM, 还可以使用 `Announcements.asStream` 可以获取到包含所有 [OnlineAnnouncement] 列表的 `Stream`. + * + * @since 2.13 + */ +public expect interface Streamable { + /** + * 创建一个能获取 [T] 的 [Flow]. + */ + public fun asFlow(): Flow + + /** + * 获取所有 [T] 列表, 将全部 [T] 都加载后再返回. + * + * @return 此时刻的 [T] 只读列表. + */ + public open suspend fun toList(): List +} \ No newline at end of file diff --git a/mirai-core-api/src/jvmBaseMain/kotlin/contact/active/GroupActive.kt b/mirai-core-api/src/jvmBaseMain/kotlin/contact/active/GroupActive.kt deleted file mode 100644 index aec9d1524..000000000 --- a/mirai-core-api/src/jvmBaseMain/kotlin/contact/active/GroupActive.kt +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2019-2022 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.contact.active - -import kotlinx.coroutines.flow.Flow -import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge -import net.mamoe.mirai.contact.Group -import net.mamoe.mirai.contact.Member -import net.mamoe.mirai.data.GroupHonorType -import net.mamoe.mirai.utils.JavaFriendlyAPI -import net.mamoe.mirai.utils.NotStableForInheritance -import java.util.stream.Stream - -/** - * 表示一个群活跃度管理. - * - * ## 获取 [GroupActive] 实例 - * - * 只可以通过 [Group.active] 获取一个群的活跃度管理, 即 [GroupActive] 实例. - * - * ### 头衔设置 - * - * * 通过 [isHonorVisible] 可以获取和设置一个群的荣誉是否显示, - * * 通过 [isTitleVisible] 可以获取和设置一个群的头衔是否显示, - * * 通过 [isTemperatureVisible] 可以获取和设置一个群的活跃度是否显示, - * * 通过 [rankTitles] 可以获取和设置一个群的等级头衔列表 (PC 端显示), - * * 通过 [temperatureTitles] 可以获取和设置一个群的活跃度头衔列表 (手机端显示) - * - * ### 刷新群成员活跃数据 - * - * 通过 [refresh] 可以刷新 [Member.active] 中的属性 (不包括 honors 和 temperature) - * - * ### 活跃度记录 - * - * 通过 [asFlow] 或 [asStream] 可以获取群活跃度记录*惰性*流, - * 在从流中收集数据时才会请求服务器获取数据. 通常建议在 Kotlin 使用协程的 [asFlow], 在 Java 使用 [asStream]. - * - * 若要获取全部活跃度记录, 可使用 [toList]. - * - * ### 活跃度图表 - * - * 通过 [queryChart] 可以获取活跃度图表, - * 包括 - * * 每日总人数 [ActiveChart.members] - * * 每日活跃人数 [ActiveChart.actives] - * * 每日申请人数 [ActiveChart.sentences] - * * 每日入群人数 [ActiveChart.join] - * * 每日退群人数 [ActiveChart.exit] - * - * 通过 [queryHonorHistory] 可以获取群荣耀历史数据, - * 包括 - * * 当前荣耀持有者 (龙王,壕礼皇冠, 善财福禄寿) [ActiveHonorList.current] - * * 群荣耀历史记录 [ActiveHonorList.records] - * - * @since 2.13 - */ -@NotStableForInheritance -public actual interface GroupActive { - - /** - * 是否在群聊中显示荣誉 - * @see MemberActive.honors - */ - public actual val isHonorVisible: Boolean - - /** - * 设置是否在群聊中显示荣誉 - * @see MemberActive.honors - */ - public actual suspend fun setHonorVisible(newValue: Boolean) - - /** - * 是否在群聊中显示头衔 - * @see Member.rankTitle - * @see Member.temperatureTitle - */ - public actual val isTitleVisible: Boolean - - /** - * 设置是否在群聊中显示头衔。操作成功时会同时刷新等级头衔信息。 - * @see Member.rankTitle - * @see Member.temperatureTitle - */ - public actual suspend fun setTitleVisible(newValue: Boolean) - - /** - * 是否在群聊中显示活跃度 - * @see MemberActive.temperature - */ - public actual val isTemperatureVisible: Boolean - - /** - * 设置是否在群聊中显示活跃度。操作成功时会同时刷新等级头衔信息。 - * @see MemberActive.temperature - */ - public actual suspend fun setTemperatureVisible(newValue: Boolean) - - /** - * 等级头衔列表,键是等级,值是头衔 - * - * @see Member.rankTitle - */ - public actual val rankTitles: Map - - /** - * 设置等级头衔列表,键是等级,值是头衔。操作成功时会同时刷新等级头衔信息。 - * @see Member.rankTitle - */ - public actual suspend fun setRankTitles(newValue: Map) - - /** - * 活跃度头衔列表,键是等级,值是头衔。操作成功时会同时刷新活跃度头衔信息。 - * @see Member.temperatureTitle - */ - public actual val temperatureTitles: Map - - /** - * 设置活跃度头衔列表,键是等级,值是头衔。操作成功时会同时刷新活跃度头衔信息。 - * @see Member.temperatureTitle - */ - public actual suspend fun setTemperatureTitles(newValue: Map) - - /** - * 刷新 [Member.active] 中的属性 (不包括 [honors][MemberActive.honors] 和 [temperature][MemberActive.temperature]) - * @see Member.active - */ - public actual suspend fun refresh() - - /** - * 创建一个能获取该群内所有群活跃度记录的 [Flow]. 在 [Flow] 被使用时才会分页下载 [ActiveRecord]. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [ActiveRecord] 和 [Flow] 的[收集][Flow.collect]. - */ - public actual fun asFlow(): Flow - - /** - * 创建一个能获取该群内所有群活跃度记录的 [Stream]. 在 [Stream] 被使用时才会分页下载 [ActiveRecord]. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [ActiveRecord] 和 [Stream] 的[收集][Stream.collect]. - * - * 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [asFlow], 因此不建议在 Kotlin 使用. 在 Kotlin 请使用 [asFlow]. - */ - @JavaFriendlyAPI - public fun asStream(): Stream - - /** - * 获取活跃度图表数据 - */ - public actual suspend fun queryChart(): ActiveChart - - /** - * 获取群荣耀历史数据, 刷新 [Member.active] 中的 [MemberActive.honors] - * @see Member.active - */ - @Suppress("INAPPLICABLE_JVM_NAME") - @JvmName("queryHonorHistory") - public actual suspend fun queryHonorHistory(type: GroupHonorType): ActiveHonorList - - /** - * 获取活跃度排行榜,通常是前五十名 - */ - public actual suspend fun queryActiveRank(): List -} \ No newline at end of file diff --git a/mirai-core-api/src/jvmBaseMain/kotlin/contact/announcement/Announcements.kt b/mirai-core-api/src/jvmBaseMain/kotlin/contact/announcement/Announcements.kt deleted file mode 100644 index b4f935298..000000000 --- a/mirai-core-api/src/jvmBaseMain/kotlin/contact/announcement/Announcements.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2019-2022 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 -@file:Suppress("INAPPLICABLE_JVM_NAME") - -package net.mamoe.mirai.contact.announcement - -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.toList -import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge -import net.mamoe.mirai.contact.Group -import net.mamoe.mirai.contact.PermissionDeniedException -import net.mamoe.mirai.utils.ExternalResource -import net.mamoe.mirai.utils.NotStableForInheritance -import java.util.stream.Stream - - -/** - * 表示一个群的公告列表 (管理器). - * - * ## 获取群公告 - * - * ### 获取 [Announcements] 实例 - * - * 只可以通过 [Group.announcements] 获取一个群的公告列表, 即 [Announcements] 实例. - * - * ### 获取公告列表 - * - * 通过 [asFlow] 或 [asStream] 可以获取到*惰性*流, 在从流中收集数据时才会请求服务器获取数据. 通常建议在 Kotlin 使用协程的 [asFlow], 在 Java 使用 [asStream]. - * - * 若要获取全部公告列表, 可使用 [toList]. - * - * ## 发布群公告 - * - * 查看 [Announcement] - * - * @since 2.7 - */ -@NotStableForInheritance -public actual interface Announcements { - /** - * 创建一个能获取该群内所有群公告列表的 [Flow]. 在 [Flow] 被使用时才会分页下载 [OnlineAnnouncement]. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [OfflineAnnouncement] 和 [Flow] 的[收集][Flow.collect]. - */ - public actual suspend fun asFlow(): Flow - - /** - * 创建一个能获取该群内所有群公告列表的 [Stream]. 在 [Stream] 被使用时才会分页下载 [OnlineAnnouncement]. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [OfflineAnnouncement] 和 [Stream] 的[收集][Stream.collect]. - * - * 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [asFlow], 因此不建议在 Kotlin 使用. 在 Kotlin 请使用 [asFlow]. - */ - public fun asStream(): Stream - - /** - * 获取所有群公告列表, 将全部 [OnlineAnnouncement] 都下载后再返回. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取并返回已经成功获取到的 [OfflineAnnouncement] 列表. - * - * @return 此时刻的群公告只读列表. - */ - public actual suspend fun toList(): List = asFlow().toList() - - - /** - * 删除一条群公告. 需要管理员权限. 使用 [OnlineAnnouncement.delete] 与此方法效果相同. - * - * @param fid 公告的 [OnlineAnnouncement.fid] - * @return 成功返回 `true`, 群公告不存在时返回 `false` - * - * @throws PermissionDeniedException 当没有权限时抛出 - * @throws IllegalStateException 当协议异常时抛出 - * - * @see OnlineAnnouncement.delete - */ - public actual suspend fun delete(fid: String): Boolean - - /** - * 获取一条群公告. - * @param fid 公告的 [OnlineAnnouncement.fid] - * @return 返回 `null` 表示不存在该 [fid] 的群公告 - * @throws IllegalStateException 当协议异常时抛出 - */ - public actual suspend fun get(fid: String): OnlineAnnouncement? - - /** - * 在该群发布群公告并获得 [OnlineAnnouncement], 需要管理员权限. 发布公告后群内将会出现 "有新公告" 系统提示. - * @throws PermissionDeniedException 当没有权限时抛出 - * @throws IllegalStateException 当协议异常时抛出 - * @see Announcement.publishTo - */ - public actual suspend fun publish(announcement: Announcement): OnlineAnnouncement - - /** - * 上传资源作为群公告图片. 返回值可用于 [AnnouncementParameters.image]. - * - * **注意**: 需要由调用方[关闭][ExternalResource.close] [resource]. - * @throws IllegalStateException 当协议异常时抛出 - */ - public actual suspend fun uploadImage(resource: ExternalResource): AnnouncementImage -} diff --git a/mirai-core-api/src/jvmBaseMain/kotlin/utils/Streamable.kt b/mirai-core-api/src/jvmBaseMain/kotlin/utils/Streamable.kt new file mode 100644 index 000000000..fbb212836 --- /dev/null +++ b/mirai-core-api/src/jvmBaseMain/kotlin/utils/Streamable.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2019-2022 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.utils + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.toList +import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge +import net.mamoe.mirai.contact.announcement.Announcement +import net.mamoe.mirai.contact.announcement.Announcements +import java.util.stream.Stream + +/** + * 表示一个可以创建数据流 [Flow] 和 [Stream] 的对象. + * + * 实现这个接口的对象可以看做为元素 [T] 的集合. + * 例如 [Announcements] 可以看作是 [Announcement] 的集合, + * 使用 [Announcements.asFlow] 可以获取到包含所有 [Announcement] 列表的 [Flow], + * 使用 [Announcements.asStream] 可以获取到包含所有 [Announcement] 列表的 [Stream]. + * + * @since 2.13 + */ +public actual interface Streamable { + /** + * 创建一个能获取 [T] 的 [Flow]. + */ + public actual fun asFlow(): Flow + + /** + * 创建一个能获取该群内所有 [T] 的 [Stream]. + * + * 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [asFlow], 因此不建议在 Kotlin 使用. 在 Kotlin 请使用 [asFlow]. + */ + public fun asStream(): Stream + + /** + * 获取所有 [T] 列表, 将全部 [T] 都加载后再返回. + * + * @return 此时刻的 [T] 只读列表. + */ + public actual suspend fun toList(): List = asFlow().toList() +} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/contact/active/GroupActive.kt b/mirai-core-api/src/nativeMain/kotlin/contact/active/GroupActive.kt deleted file mode 100644 index 2ed8b45d7..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/contact/active/GroupActive.kt +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2019-2022 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 - */ - -package net.mamoe.mirai.contact.active - -import kotlinx.coroutines.flow.Flow -import net.mamoe.mirai.contact.Group -import net.mamoe.mirai.contact.Member -import net.mamoe.mirai.data.GroupHonorType -import net.mamoe.mirai.utils.NotStableForInheritance - -/** - * 表示一个群活跃度管理. - * - * ## 获取 [GroupActive] 实例 - * - * 只可以通过 [Group.active] 获取一个群的活跃度管理, 即 [GroupActive] 实例. - * - * ### 头衔设置 - * - * * 通过 [isHonorVisible] 可以获取和设置一个群的荣誉是否显示, - * * 通过 [isTitleVisible] 可以获取和设置一个群的头衔是否显示, - * * 通过 [isTemperatureVisible] 可以获取和设置一个群的活跃度是否显示, - * * 通过 [rankTitles] 可以获取和设置一个群的等级头衔列表 (PC 端显示), - * * 通过 [temperatureTitles] 可以获取和设置一个群的活跃度头衔列表 (手机端显示) - * - * ### 刷新群成员活跃数据 - * - * 通过 [refresh] 可以刷新 [Member.active] 中的属性 (不包括 honors 和 temperature) - * - * ### 活跃度记录 - * - * 通过 [asFlow] 可以获取群活跃度记录*惰性*流. - * - * 若要获取全部活跃度记录, 可使用 [toList]. - * - * ### 活跃度图表 - * - * 通过 [queryChart] 可以获取活跃度图表, - * 包括 - * * 每日总人数 [ActiveChart.members] - * * 每日活跃人数 [ActiveChart.actives] - * * 每日申请人数 [ActiveChart.sentences] - * * 每日入群人数 [ActiveChart.join] - * * 每日退群人数 [ActiveChart.exit] - * - * 通过 [queryHonorHistory] 可以获取群荣耀历史数据, - * 包括 - * * 当前荣耀持有者 (龙王,壕礼皇冠, 善财福禄寿) [ActiveHonorList.current] - * * 群荣耀历史记录 [ActiveHonorList.records] - * - * @since 2.13 - */ -@NotStableForInheritance -public actual interface GroupActive { - - /** - * 是否在群聊中显示荣誉 - * @see MemberActive.honors - */ - public actual val isHonorVisible: Boolean - - /** - * 设置是否在群聊中显示荣誉 - * @see MemberActive.honors - */ - public actual suspend fun setHonorVisible(newValue: Boolean) - - /** - * 是否在群聊中显示头衔 - * @see Member.rankTitle - * @see Member.temperatureTitle - */ - public actual val isTitleVisible: Boolean - - /** - * 设置是否在群聊中显示头衔。操作成功时会同时刷新等级头衔信息。 - * @see Member.rankTitle - * @see Member.temperatureTitle - */ - public actual suspend fun setTitleVisible(newValue: Boolean) - - /** - * 是否在群聊中显示活跃度 - * @see MemberActive.temperature - */ - public actual val isTemperatureVisible: Boolean - - /** - * 设置是否在群聊中显示活跃度。操作成功时会同时刷新等级头衔信息。 - * @see MemberActive.temperature - */ - public actual suspend fun setTemperatureVisible(newValue: Boolean) - - /** - * 等级头衔列表,键是等级,值是头衔 - * - * @see Member.rankTitle - */ - public actual val rankTitles: Map - - /** - * 设置等级头衔列表,键是等级,值是头衔。操作成功时会同时刷新等级头衔信息。 - * @see Member.rankTitle - */ - public actual suspend fun setRankTitles(newValue: Map) - - /** - * 活跃度头衔列表,键是等级,值是头衔。操作成功时会同时刷新活跃度头衔信息。 - * @see Member.temperatureTitle - */ - public actual val temperatureTitles: Map - - /** - * 设置活跃度头衔列表,键是等级,值是头衔。操作成功时会同时刷新活跃度头衔信息。 - * @see Member.temperatureTitle - */ - public actual suspend fun setTemperatureTitles(newValue: Map) - - /** - * 刷新 [Member.active] 中的属性 (不包括 [honors][MemberActive.honors] 和 [temperature][MemberActive.temperature]) - * @see Member.active - */ - public actual suspend fun refresh() - - /** - * 创建一个能获取该群内所有群活跃度记录的 [Flow]. 在 [Flow] 被使用时才会分页下载 [ActiveRecord]. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [ActiveRecord] 和 [Flow] 的[收集][Flow.collect]. - */ - public actual fun asFlow(): Flow - - /** - * 获取活跃度图表数据 - */ - public actual suspend fun queryChart(): ActiveChart - - /** - * 获取群荣耀历史数据, 刷新 [Member.active] 中的 [MemberActive.honors] - * @see Member.active - */ - public actual suspend fun queryHonorHistory(type: GroupHonorType): ActiveHonorList - - /** - * 获取活跃度排行榜,通常是前五十名 - */ - public actual suspend fun queryActiveRank(): List -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/contact/announcement/Announcements.kt b/mirai-core-api/src/nativeMain/kotlin/contact/announcement/Announcements.kt deleted file mode 100644 index 3357fed7b..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/contact/announcement/Announcements.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2019-2022 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 - */ - -package net.mamoe.mirai.contact.announcement - -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.toList -import net.mamoe.mirai.contact.Group -import net.mamoe.mirai.contact.PermissionDeniedException -import net.mamoe.mirai.utils.ExternalResource -import net.mamoe.mirai.utils.NotStableForInheritance - -/** - * 表示一个群的公告列表 (管理器). - * - * ## 获取群公告 - * - * ### 获取 [Announcements] 实例 - * - * 只可以通过 [Group.announcements] 获取一个群的公告列表, 即 [Announcements] 实例. - * - * ### 获取公告列表 - * - * 通过 [asFlow] 可以获取到*惰性*流, 在从流中收集数据时才会请求服务器获取数据. - * - * 若要获取全部公告列表, 可使用 [toList]. - * - * ## 发布群公告 - * - * 查看 [Announcement] - * - * @since 2.7 - */ -@NotStableForInheritance -public actual interface Announcements { - /** - * 创建一个能获取该群内所有群公告列表的 [Flow]. 在 [Flow] 被使用时才会分页下载 [OnlineAnnouncement]. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [OfflineAnnouncement] 和 [Flow] 的[收集][Flow.collect]. - */ - public actual suspend fun asFlow(): Flow - - /** - * 获取所有群公告列表, 将全部 [OnlineAnnouncement] 都下载后再返回. - * - * 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取并返回已经成功获取到的 [OfflineAnnouncement] 列表. - * - * @return 此时刻的群公告只读列表. - */ - public actual suspend fun toList(): List = asFlow().toList() - - - /** - * 删除一条群公告. 需要管理员权限. 使用 [OnlineAnnouncement.delete] 与此方法效果相同. - * - * @param fid 公告的 [OnlineAnnouncement.fid] - * @return 成功返回 `true`, 群公告不存在时返回 `false` - * - * @throws PermissionDeniedException 当没有权限时抛出 - * @throws IllegalStateException 当协议异常时抛出 - * - * @see OnlineAnnouncement.delete - */ - public actual suspend fun delete(fid: String): Boolean - - /** - * 获取一条群公告. - * @param fid 公告的 [OnlineAnnouncement.fid] - * @return 返回 `null` 表示不存在该 [fid] 的群公告 - * @throws IllegalStateException 当协议异常时抛出 - */ - public actual suspend fun get(fid: String): OnlineAnnouncement? - - /** - * 在该群发布群公告并获得 [OnlineAnnouncement], 需要管理员权限. 发布公告后群内将会出现 "有新公告" 系统提示. - * @throws PermissionDeniedException 当没有权限时抛出 - * @throws IllegalStateException 当协议异常时抛出 - * @see Announcement.publishTo - */ - public actual suspend fun publish(announcement: Announcement): OnlineAnnouncement - - /** - * 上传资源作为群公告图片. 返回值可用于 [AnnouncementParameters.image]. - * - * **注意**: 需要由调用方[关闭][ExternalResource.close] [resource]. - * @throws IllegalStateException 当协议异常时抛出 - */ - public actual suspend fun uploadImage(resource: ExternalResource): AnnouncementImage -} diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/Streamable.kt b/mirai-core-api/src/nativeMain/kotlin/utils/Streamable.kt new file mode 100644 index 000000000..a726cbab1 --- /dev/null +++ b/mirai-core-api/src/nativeMain/kotlin/utils/Streamable.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2019-2022 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 + */ + +package net.mamoe.mirai.utils + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.toList +import net.mamoe.mirai.contact.announcement.Announcement +import net.mamoe.mirai.contact.announcement.Announcements + +/** + * 表示一个可以创建[数据流][Flow]的对象. + * + * 实现这个接口的对象可以看做为元素 [T] 的集合. + * 例如 [Announcements] 可以看作是 [Announcement] 的集合, + * 使用 [Announcements.asFlow] 可以获取到包含所有 [Announcement] 列表的 [Flow] + * 在 JVM, 还可以使用 `Announcements.asStream` 可以获取到包含所有 [Announcement] 列表的 `Stream`. + * + * @since 2.13 + */ +public actual interface Streamable { + /** + * 创建一个能获取 [T] 的 [Flow]. + */ + public actual fun asFlow(): Flow + + /** + * 获取所有 [T] 列表, 将全部 [T] 都加载后再返回. + * + * @return 此时刻的 [T] 只读列表. + */ + public actual suspend fun toList(): List = asFlow().toList() +} \ No newline at end of file diff --git a/mirai-core-mock/src/internal/contact/MockAnnouncementsImpl.kt b/mirai-core-mock/src/internal/contact/MockAnnouncementsImpl.kt index 73156d1c2..b255aafdb 100644 --- a/mirai-core-mock/src/internal/contact/MockAnnouncementsImpl.kt +++ b/mirai-core-mock/src/internal/contact/MockAnnouncementsImpl.kt @@ -35,7 +35,7 @@ internal class MockAnnouncementsImpl( ) : MockAnnouncements { val announcements = ConcurrentHashMap() - override suspend fun asFlow(): Flow = announcements.values.asFlow() + override fun asFlow(): Flow = announcements.values.asFlow() override fun asStream(): Stream = announcements.values.toList().stream() diff --git a/mirai-core/src/commonMain/kotlin/contact/announcement/AnnouncementsImpl.kt b/mirai-core/src/commonMain/kotlin/contact/announcement/AnnouncementsImpl.kt index ee03b3c9b..754359f91 100644 --- a/mirai-core/src/commonMain/kotlin/contact/announcement/AnnouncementsImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/announcement/AnnouncementsImpl.kt @@ -7,8 +7,6 @@ * https://github.com/mamoe/mirai/blob/dev/LICENSE */ -@file:Suppress("DEPRECATION") - package net.mamoe.mirai.internal.contact.announcement import io.ktor.client.request.* @@ -67,7 +65,7 @@ internal abstract class CommonAnnouncementsImpl( }.rightOrNull } - override suspend fun asFlow(): Flow { + override fun asFlow(): Flow { return flow { var i = 1 while (true) { diff --git a/mirai-core/src/commonMain/kotlin/network/highway/ChunkedFlowSession.kt b/mirai-core/src/commonMain/kotlin/network/highway/ChunkedFlowSession.kt index 65e3b04ca..15aadace4 100644 --- a/mirai-core/src/commonMain/kotlin/network/highway/ChunkedFlowSession.kt +++ b/mirai-core/src/commonMain/kotlin/network/highway/ChunkedFlowSession.kt @@ -44,5 +44,5 @@ internal class ChunkedFlowSession( } } - internal suspend fun asFlow(): Flow = flow { useAll { emit(it) } } // 'single thread' producer + internal fun asFlow(): Flow = flow { useAll { emit(it) } } // 'single thread' producer } \ No newline at end of file