|
|
@@ -9,3 +9,104 @@
|
|
|
|
|
|
package net.mamoe.mirai.event
|
|
|
|
|
|
+import kotlinx.coroutines.*
|
|
|
+import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
|
|
+import kotlin.coroutines.CoroutineContext
|
|
|
+import kotlin.coroutines.EmptyCoroutineContext
|
|
|
+
|
|
|
+/**
|
|
|
+ * 监听这个事件, 并尝试从这个事件中获取一个值.
|
|
|
+ *
|
|
|
+ * 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
|
|
+ *
|
|
|
+ * @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
|
|
+ * @param filter 过滤器. 返回非 null 则代表得到了需要的值. [subscribingGet] 会返回这个值
|
|
|
+ *
|
|
|
+ * @see subscribingGetAsync 本函数的异步版本
|
|
|
+ */
|
|
|
+@MiraiExperimentalAPI
|
|
|
+suspend inline fun <reified E : Event, R : Any> subscribingGet(
|
|
|
+ timeoutMillis: Long = -1,
|
|
|
+ noinline filter: E.(E) -> R?
|
|
|
+): R {
|
|
|
+ require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
|
|
|
+ return subscribingGetOrNull(timeoutMillis, filter) ?: error("timeout subscribingGet")
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 监听这个事件, 并尝试从这个事件中获取一个值.
|
|
|
+ *
|
|
|
+ * 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
|
|
+ *
|
|
|
+ * @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
|
|
+ * @param filter 过滤器. 返回非 null 则代表得到了需要的值. [subscribingGet] 会返回这个值
|
|
|
+ *
|
|
|
+ * @see subscribingGetAsync 本函数的异步版本
|
|
|
+ */
|
|
|
+@MiraiExperimentalAPI
|
|
|
+suspend inline fun <reified E : Event, R : Any> subscribingGetOrNull(
|
|
|
+ timeoutMillis: Long = -1,
|
|
|
+ noinline filter: E.(E) -> R?
|
|
|
+): R? {
|
|
|
+ require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
|
|
|
+ var result: R? = null
|
|
|
+ var resultThrowable: Throwable? = null
|
|
|
+
|
|
|
+ if (timeoutMillis == -1L) {
|
|
|
+ @Suppress("DuplicatedCode") // for better performance
|
|
|
+ coroutineScope {
|
|
|
+ var listener: Listener<E>? = null
|
|
|
+ listener = this.subscribe {
|
|
|
+ val value = try {
|
|
|
+ filter.invoke(this, it)
|
|
|
+ } catch (e: Exception) {
|
|
|
+ resultThrowable = e
|
|
|
+ return@subscribe ListeningStatus.STOPPED.also { listener!!.complete() }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (value != null) {
|
|
|
+ result = value
|
|
|
+ return@subscribe ListeningStatus.STOPPED.also { listener!!.complete() }
|
|
|
+ } else return@subscribe ListeningStatus.LISTENING
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ withTimeoutOrNull(timeoutMillis) {
|
|
|
+ var listener: Listener<E>? = null
|
|
|
+ @Suppress("DuplicatedCode") // for better performance
|
|
|
+ listener = this.subscribe {
|
|
|
+ val value = try {
|
|
|
+ filter.invoke(this, it)
|
|
|
+ } catch (e: Exception) {
|
|
|
+ resultThrowable = e
|
|
|
+ return@subscribe ListeningStatus.STOPPED.also { listener!!.complete() }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (value != null) {
|
|
|
+ result = value
|
|
|
+ return@subscribe ListeningStatus.STOPPED.also { listener!!.complete() }
|
|
|
+ } else return@subscribe ListeningStatus.LISTENING
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ resultThrowable?.let { throw it }
|
|
|
+ return result
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 异步监听这个事件, 并尝试从这个事件中获取一个值.
|
|
|
+ *
|
|
|
+ * 若 [filter] 抛出了一个异常, [Deferred.await] 会抛出这个异常或.
|
|
|
+ *
|
|
|
+ * @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
|
|
+ * @param coroutineContext 额外的 [CoroutineContext]
|
|
|
+ * @param filter 过滤器. 返回非 null 则代表得到了需要的值. [subscribingGet] 会返回这个值
|
|
|
+ */
|
|
|
+@MiraiExperimentalAPI
|
|
|
+inline fun <reified E : Event, R : Any> CoroutineScope.subscribingGetAsync(
|
|
|
+ coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
|
|
+ timeoutMillis: Long = -1,
|
|
|
+ noinline filter: E.(E) -> R?
|
|
|
+): Deferred<R> = this.async(coroutineContext) {
|
|
|
+ subscribingGet(timeoutMillis, filter)
|
|
|
+}
|