[core] Introduce Streamable for simplified multiplatform asFlow a… (#2256)

* [core] Introduce `Streamable` for simplified multiplatform `asFlow` and `asStream`. Make `Announcements.asFlow` not suspend.

* Remove `@JvmBlockingBridge` in native
This commit is contained in:
Him188 2022-09-25 23:44:18 +08:00 committed by GitHub
parent 2da0a2d6d3
commit 16609fb1e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 180 additions and 586 deletions

View File

@ -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

View File

@ -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

View File

@ -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<ActiveRecord> {
/**
* 是否在群聊中显示荣誉
@ -133,13 +133,6 @@ public expect interface GroupActive {
*/
public suspend fun refresh()
/**
* 创建一个能获取该群内所有群活跃度记录的 [Flow]. [Flow] 被使用时才会分页下载 [ActiveRecord].
*
* 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [ActiveRecord] [Flow] [收集][Flow.collect].
*/
public fun asFlow(): Flow<ActiveRecord>
/**
* 获取活跃度图表数据
*/

View File

@ -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>
/**
* 获取所有群公告列表, 将全部 [OnlineAnnouncement] 都下载后再返回.
*
* 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取并返回已经成功获取到的 [OfflineAnnouncement] 列表.
*
* @return 此时刻的群公告只读列表.
*/
public open suspend fun toList(): List<OnlineAnnouncement>
public interface Announcements : Streamable<OnlineAnnouncement> {
/**
* 删除一条群公告. 需要管理员权限. 使用 [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<OnlineAnnouncement> = asFlow()
}

View File

@ -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> {
/**
* 创建一个能获取 [T] [Flow].
*/
public fun asFlow(): Flow<T>
/**
* 获取所有 [T] 列表, 将全部 [T] 都加载后再返回.
*
* @return 此时刻的 [T] 只读列表.
*/
public open suspend fun toList(): List<T>
}

View File

@ -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<Int, String>
/**
* 设置等级头衔列表键是等级值是头衔操作成功时会同时刷新等级头衔信息
* @see Member.rankTitle
*/
public actual suspend fun setRankTitles(newValue: Map<Int, String>)
/**
* 活跃度头衔列表键是等级值是头衔操作成功时会同时刷新活跃度头衔信息
* @see Member.temperatureTitle
*/
public actual val temperatureTitles: Map<Int, String>
/**
* 设置活跃度头衔列表键是等级值是头衔操作成功时会同时刷新活跃度头衔信息
* @see Member.temperatureTitle
*/
public actual suspend fun setTemperatureTitles(newValue: Map<Int, String>)
/**
* 刷新 [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<ActiveRecord>
/**
* 创建一个能获取该群内所有群活跃度记录的 [Stream]. [Stream] 被使用时才会分页下载 [ActiveRecord].
*
* 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [ActiveRecord] [Stream] [收集][Stream.collect].
*
* 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [asFlow], 因此不建议在 Kotlin 使用. Kotlin 请使用 [asFlow].
*/
@JavaFriendlyAPI
public fun asStream(): Stream<ActiveRecord>
/**
* 获取活跃度图表数据
*/
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<ActiveRankRecord>
}

View File

@ -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<OnlineAnnouncement>
/**
* 创建一个能获取该群内所有群公告列表的 [Stream]. [Stream] 被使用时才会分页下载 [OnlineAnnouncement].
*
* 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取, 不影响已经成功获取的 [OfflineAnnouncement] [Stream] [收集][Stream.collect].
*
* 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [asFlow], 因此不建议在 Kotlin 使用. Kotlin 请使用 [asFlow].
*/
public fun asStream(): Stream<OnlineAnnouncement>
/**
* 获取所有群公告列表, 将全部 [OnlineAnnouncement] 都下载后再返回.
*
* 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取并返回已经成功获取到的 [OfflineAnnouncement] 列表.
*
* @return 此时刻的群公告只读列表.
*/
public actual suspend fun toList(): List<OnlineAnnouncement> = 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
}

View File

@ -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> {
/**
* 创建一个能获取 [T] [Flow].
*/
public actual fun asFlow(): Flow<T>
/**
* 创建一个能获取该群内所有 [T] [Stream].
*
* 实现细节: 为了适合 Java 调用, 实现类似为阻塞式的 [asFlow], 因此不建议在 Kotlin 使用. Kotlin 请使用 [asFlow].
*/
public fun asStream(): Stream<T>
/**
* 获取所有 [T] 列表, 将全部 [T] 都加载后再返回.
*
* @return 此时刻的 [T] 只读列表.
*/
public actual suspend fun toList(): List<T> = asFlow().toList()
}

View File

@ -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<Int, String>
/**
* 设置等级头衔列表键是等级值是头衔操作成功时会同时刷新等级头衔信息
* @see Member.rankTitle
*/
public actual suspend fun setRankTitles(newValue: Map<Int, String>)
/**
* 活跃度头衔列表键是等级值是头衔操作成功时会同时刷新活跃度头衔信息
* @see Member.temperatureTitle
*/
public actual val temperatureTitles: Map<Int, String>
/**
* 设置活跃度头衔列表键是等级值是头衔操作成功时会同时刷新活跃度头衔信息
* @see Member.temperatureTitle
*/
public actual suspend fun setTemperatureTitles(newValue: Map<Int, String>)
/**
* 刷新 [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<ActiveRecord>
/**
* 获取活跃度图表数据
*/
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<ActiveRankRecord>
}

View File

@ -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>
/**
* 获取所有群公告列表, 将全部 [OnlineAnnouncement] 都下载后再返回.
*
* 异常不会抛出, 只会记录到网络日志. 当获取发生异常时将会终止获取并返回已经成功获取到的 [OfflineAnnouncement] 列表.
*
* @return 此时刻的群公告只读列表.
*/
public actual suspend fun toList(): List<OnlineAnnouncement> = 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
}

View File

@ -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> {
/**
* 创建一个能获取 [T] [Flow].
*/
public actual fun asFlow(): Flow<T>
/**
* 获取所有 [T] 列表, 将全部 [T] 都加载后再返回.
*
* @return 此时刻的 [T] 只读列表.
*/
public actual suspend fun toList(): List<T> = asFlow().toList()
}

View File

@ -35,7 +35,7 @@ internal class MockAnnouncementsImpl(
) : MockAnnouncements {
val announcements = ConcurrentHashMap<String, OnlineAnnouncement>()
override suspend fun asFlow(): Flow<OnlineAnnouncement> = announcements.values.asFlow()
override fun asFlow(): Flow<OnlineAnnouncement> = announcements.values.asFlow()
override fun asStream(): Stream<OnlineAnnouncement> = announcements.values.toList().stream()

View File

@ -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<OnlineAnnouncement> {
override fun asFlow(): Flow<OnlineAnnouncement> {
return flow {
var i = 1
while (true) {

View File

@ -44,5 +44,5 @@ internal class ChunkedFlowSession<T>(
}
}
internal suspend fun asFlow(): Flow<T> = flow { useAll { emit(it) } } // 'single thread' producer
internal fun asFlow(): Flow<T> = flow { useAll { emit(it) } } // 'single thread' producer
}